paperclipai/paperclip · error
opencode_run_attach_invalid
opencode_run_attach_invalid
Error message
opencode_run_attach_invalid
What it means
After the busy check, attachRun validates that input.runId is non-empty; an empty string, null, or undefined throws opencode_run_attach_invalid because the driver cannot bind result tracking without a run identifier.
Source
Thrown at packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts:509
opencodeVersion: input.runtime.version,
},
},
{ itemId: `${input.providerSessionId}:model` },
);
}
ids() {
return {
driverSessionId: this.#providerSessionId,
providerSessionId: this.#providerSessionId,
displayId: this.#providerSessionId,
};
}
attachRun(input: { runId: string }): void {
if (this.#activeTurnId !== null)
throw new Error("opencode_run_attach_busy");
if (!input.runId) throw new Error("opencode_run_attach_invalid");
this.#runId = input.runId;
this.#result = null;
this.#resultFingerprint = null;
this.#resultCallId = null;
this.#resultTurnId = null;
this.#semanticResultTextBoundary = null;
this.#semanticResultProviderMessageId = null;
this.#lastNonTerminalToolSourceSeq = 0;
this.#completedTextPartIds.clear();
this.#completedReasoningPartIds.clear();
this.#completedTextParts.length = 0;
this.#terminalTurns.clear();
this.#sendFullContext = false;
this.#emit("run.attached", { runId: input.runId, sameSession: true });
}
events(): AsyncIterable<PrpEvent> {
return this.#events;View on GitHub (pinned to 01ad858492)
Solutions
- Create/resolve the run id before attachRun and assert it's a non-empty string at the call site.
- Check upstream code that constructs the run record — ensure the id is generated and returned.
- Validate run payloads at the boundary (schema/zod) so missing ids fail earlier with a clear message.
- Pass a deterministic id (e.g. uuid) if the caller legitimately has no persistence-backed id yet.
Example fix
// before
driver.attachRun({ runId: run?.id ?? '' }); // silently empty -> throws
// after
if (!run?.id) throw new Error(`run record missing id: ${JSON.stringify(run)}`);
driver.attachRun({ runId: run.id }); Defensive patterns
Strategy: validation
Validate before calling
const assertRunId = (id: string | undefined): string => { if (typeof id !== 'string' || id.length === 0) throw new Error('attachRun requires a non-empty runId'); return id; }; Type guard
const isRunId = (v: unknown): v is string => typeof v === 'string' && v.length > 0;
Try / catch
try { driver.attachRun({ runId }); } catch (e) { if ((e as Error).message === 'opencode_run_attach_invalid') { console.error('runId was empty; run record likely unpersisted', { runId }); throw new Error('Create and persist the run record before attaching', { cause: e }); } throw e; } Prevention
- Validate run payloads with a schema so missing ids fail at the boundary
- Generate a deterministic uuid run id if persistence lags behind attach
- Never default runId to '' with ?? ''; fail loudly instead
- Ensure the run-creation API returns the id before the runner proceeds
When it happens
Trigger: Calling attachRun({ runId: '' }) or with runId omitted — usually a runner bug where the run record wasn't created/persisted before attaching, or an id field read from an API response that was undefined.
Common situations: Database row not yet assigned an id, destructuring a missing field from a run payload, template string defaults collapsing to empty string, migration gaps leaving runs without identifiers.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- OpenCode proxy requires model in provider/model form
- Warm run transition binding is invalid.
- opencode_run_attach_busy
- Invalid semantic result
- OpenCode working directory must not be a filesystem root
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/fdfb68b9bde6d416.
Report an issue: GitHub.