iOfficeAI/OfficeCLI · error · OfficeCliError
-1
-1
Error message
resident is running but the command could not be delivered (pipe busy or unresponsive); retry, or close and reopen [${e.message}] What it means
Raised by rpc() (code -1) when the resident's pipe cannot be connected to / written within BUSY_MAX_RETRIES (3) attempts with backoff, mirroring officecli's TrySend busy-delivery policy. Because every retry happens BEFORE the command executes, re-sending is safe; this error means even the generous connect budget (30s) was exhausted. The message embeds the underlying socket error.
Source
Thrown at sdk/node/index.js:208
* retries with backoff, then a blocking read. A retry only re-attempts the
* connect (before the command runs), so it never double-applies a mutation. If
* the command still can't be delivered, raise a busy/unresponsive error — never
* fall back to touching the file directly (that would race the resident).
*
* `maxRetries` overrides the busy-retry count. Liveness probes (serves) pass 0
* so a missing/stale pipe fails FAST instead of sleeping through the backoff.
*/
async function rpc(sockPath, req, connectTimeoutMs = BUSY_CONNECT_TIMEOUT_MS, maxRetries = BUSY_MAX_RETRIES) {
const line = Buffer.from(JSON.stringify(req) + '\n', 'utf8');
let raw = null;
for (let attempt = 0; ; attempt++) {
try {
raw = await sendOnce(sockPath, line, connectTimeoutMs);
break;
} catch (e) {
// Connect/socket error only — the command never ran, so a retry is safe.
if (attempt >= maxRetries) {
throw new OfficeCliError(
-1,
'resident is running but the command could not be delivered ' +
`(pipe busy or unresponsive); retry, or close and reopen [${e.message}]`
);
}
await sleep(50 * (attempt + 1)); // = TrySend's 50*(n+1)ms backoff
}
}
const text = decodeLine(raw);
if (!text.trim()) {
// Empty/closed reply: the resident accepted the connection but closed
// without a complete response (e.g. crashed mid-serve). We refuse to
// re-send — the command may already have been APPLIED before the resident
// died, so re-sending would double-apply a non-idempotent op — and raise
// instead. _cmd's recovery then restarts a dead resident and retries once.
throw new OfficeCliError(
-1,
'resident closed the connection without a response ' +View on GitHub (pinned to 1ced45e900)
Solutions
- Simply retry the call (send/batch) — the failure occurred before the command ran, so a retry cannot double-apply.
- Reduce concurrency against the shared resident (serialize or queue your sends) so the connect budget is not exhausted.
- Call doc.close() then oc.open() again to restart a resident that appears wedged.
- Raise the per-call timeout via the timeoutMs argument if the resident is legitimately busy for long periods.
Example fix
// before: doc.send(...) -> [exit -1] resident is running but the command could not be delivered
// after: retry idempotently with backoff
async function sendRetry(doc, item, tries = 4) {
for (let i = 0; i < tries; i++) {
try { return await doc.send(item); }
catch (e) { if (e.code !== -1 || i === tries - 1) throw e; await new Promise(r => setTimeout(r, 100 * (i + 1))); }
}
} Defensive patterns
Strategy: retry
Try / catch
// Safe retry: the failure happens BEFORE the command runs, so re-send cannot double-apply
async function sendResilient(doc, item, { tries = 4, base = 100 } = {}) {
for (let i = 0; ; i++) {
try { return await doc.send(item); }
catch (e) {
const busy = e.code === -1 && /could not be delivered/.test(e.message);
if (!busy || i >= tries - 1) throw e;
await new Promise(r => setTimeout(r, base * (i + 1)));
}
}
} Prevention
- Serialize or bound concurrency against one resident (the pipe is a serialized queue).
- Pass a generous timeoutMs for legitimately long operations.
- Retry on code -1 'could not be delivered' — it is pre-execution and idempotent to retry.
When it happens
Trigger: The resident is alive but saturated: a long-running command holds the serialized queue and all connect attempts time out; too many concurrent SDK clients contending for one named pipe; the OS pipe backlog is full; transient ECONNREFUSED/EAGAIN while the resident is mid-handshake.
Common situations: A large batch over a slow doc; many parallel workers sharing one resident; a resident stuck in a slow save; the pipe briefly unavailable during a restart window.
Related errors
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/cac109133738ad42.
Report an issue: GitHub.