For AI agents: markdown of this page — /docs-content-en/infra/servers/unstick.md documentation index — /llms.txt
Unstick the channel
POST /v1/infra/servers/:id/unstick
Forcibly frees the command execution channel on the server: releases the server-side operation lock and bounces the agent tunnel. The virtual machine is not rebooted.
This is the recovery path after the 409 EXEC_BUSY refusal returned by Run a command and by a deploy. The normal order puts this call FIRST: retries at the Retry-After interval, then unsticking the channel — it is guarded, so while a lock is still observed it answers 409 OPERATION_IN_PROGRESS, and it clears a lock by itself only when that lock is an exec mutex past its own TTL. The unconditional Release a stuck lock comes after it, and only once the server is independently confirmed idle — by its state and its logs.
Parameters
| Parameter | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
id |
path | string (UUID) | yes | — | ID of a STANDALONE server. List: GET /v1/infra/servers |
force |
query | string | no | — | true or 1 — unstick even when an operation lock is detected or the lock check is unavailable. This can interrupt a running operation. Without the parameter, a detected lock returns 409 OPERATION_IN_PROGRESS; an unavailable check returns 503 LOCK_STATE_UNAVAILABLE |
The request body is empty.
Examples
curl — personal key
curl -X POST -H "X-Api-Key: YOUR_API_KEY" \
https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/unstick
curl — OAuth application
curl -X POST -H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/unstick
JavaScript — personal key
const res = await fetch(
`https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/unstick`,
{ method: 'POST', headers: { 'X-Api-Key': 'YOUR_API_KEY' } }
)
const body = await res.json()
if (!body.success) {
console.error(body.error.code, body.error.message)
} else if (!body.data.reconnected) {
console.log('The agent is still reconnecting — retry your command in a few seconds')
}
JavaScript — OAuth application
const res = await fetch(
`https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/unstick`,
{
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
},
}
)
To unstick while an operation is running, send the same request with ?force=true in the query string.
Response fields
| Field | Type | Description |
|---|---|---|
success |
boolean | true when the channel was freed |
data.backendLockReleased |
boolean | The server-side operation lock was released |
data.agentBounced |
boolean | The agent tunnel was bounced. false when there was nothing to bounce — the agent was not connected, or the server is asleep |
data.reconnected |
boolean | The agent was confirmed to have reconnected within the wait window. false means the wait window expired, not that the reconnect failed |
Response example
{
"success": true,
"data": {
"backendLockReleased": true,
"agentBounced": true,
"reconnected": true
}
}
Error response example
404 — the server was not found:
{
"success": false,
"error": {
"code": "SERVER_NOT_FOUND",
"message": "Server not found"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| 401 | MISSING_API_KEY |
The X-Api-Key header was not provided |
| 401 | INVALID_API_KEY |
The key is not recognized — no such key exists on the platform |
| 403 | INFRA_FORBIDDEN_FOR_COWORK_KEY |
The call was made with a Cowork/Code key — such a key works with data only and cannot perform write operations. To issue a key that can, see Project key for deploy |
| 404 | SERVER_NOT_FOUND |
The server does not exist, was deleted, or belongs to a different API key. Being on the server's development team does not grant access to this operation — it requires the managing key regardless of your role. The same code arrives if the server record disappeared between the access check and the unsticking. |
| 409 | OPERATION_IN_PROGRESS |
An operation lock was detected. The channel was not reset. If the operation type is known, it is included in message. A held lock does not establish that the command is healthy. Retry with force=true only if you intend to interrupt the operation |
| 409 | CONFLICT |
An unstick is already in progress for this server — wait for it to finish and retry |
| 409 | GALAXY_UNSTICK_UNSUPPORTED |
A server of kind GALAXY or GALAXY_APP: the command execution channel is shared by every application on the host, and bouncing it would abort the neighbours' commands. If the busy state persists, contact support: releasing a shared host is a platform-team action |
| 429 | RATE_LIMITED |
The limit of 6 requests per minute per "API key + server" pair was exceeded. The exact value arrives in the x-ratelimit-limit header (the cap is divided across replicas) |
| 502 | GATEWAY_ERROR |
The server-side lock was released, but the agent tunnel could not be bounced — the Gateway is unreachable. Recovery is incomplete — retry the request |
| 503 | LOCK_STATE_UNAVAILABLE |
The operation lock could not be checked. No server-side lock release or tunnel bounce was attempted. Retry later |
Full list of common API errors — Errors.
Known specifics
The lock check observes the current state. A held shared operation lock keeps the refusal, but not every one does: when the holder record outlived its own TTL and it was a command (
op: exec), the call goes through — the channel is reset, the tunnel bounced, the answer is200. The same expired record for a deploy does NOT lift the refusal: a legitimate deploy outlives its TTL. The check does not reserve the channel: an operation may start afterwards, and some operations may run without a shared lock when the database is unavailable. Absence of a refusal does not guarantee that no commands are running.What happens to the stuck command. Bouncing the tunnel makes the agent terminate the stuck command's process group and connect again. The application service is not restarted, the files on disk are untouched, and the agent is not reinstalled — unlike Repair the tunnel, which reinstalls the agent outright.
Unsticking does not wake a sleeping server. If the server is in
sleepingstatus or waking is blocked for it, there is no tunnel and nothing to bounce: the platform releases the server-side lock and answers with success andagentBounced: false.The reconnect wait window is short and does not change the outcome. The platform watches the tunnel for a few seconds after the bounce and answers without waiting any longer. The agent reconnects on its own, so
reconnected: falsemeans "not seen yet" rather than "did not come back" — retry your command a few seconds later.