{"record":{"id":"0a0c2be89d81a251","repo":"paperclipai/paperclip","slug":"steering-is-unavailable","errorCode":null,"errorMessage":"steering is unavailable","messagePattern":"steering is unavailable","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/backends/harness-driver-backend.ts","lineNumber":682,"sourceCode":"    this.#assertProtocolIntegrity();\n    try {\n      const started = await this.#session.startTurn(input);\n      this.#assertProtocolIntegrity();\n      return started;\n    } catch (error) {\n      this.#rethrowProtocolIntegrity(error);\n      throw error;\n    }\n  }\n\n  steer(input: {\n    turnId: string;\n    message: { role: \"user\"; text: string };\n    correlationId?: string;\n  }) {\n    this.#assertProtocolIntegrity();\n    if (this.#session.steer === undefined)\n      throw new Error(\"steering is unavailable\");\n    return this.#withProtocolIntegrity(() => this.#session.steer!(input));\n  }\n\n  interrupt(input: { turnId?: string; reason?: string }) {\n    if (this.#session.interrupt === undefined)\n      throw new Error(\"interruption is unavailable\");\n    return this.#session.interrupt(input);\n  }\n\n  cancel(input: { reason: string; signal: AbortSignal }) {\n    if (input.signal.aborted) {\n      throw (\n        input.signal.reason ?? new Error(\"native session cancellation aborted\")\n      );\n    }\n    // This flag is the adapter's synchronous publication boundary. Provider\n    // interruption happens afterward as passive cleanup, so a slow or broken\n    // transport cannot synthesize or publish new accepted output for the turn.","sourceCodeStart":664,"sourceCodeEnd":700,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/backends/harness-driver-backend.ts#L664-L700","documentation":"steer forwards a mid-turn user message to the underlying HarnessSession's optional steer capability. When the session driver does not implement steer (this.#session.steer === undefined), the backend throws \"steering is unavailable\" because the driver cannot inject messages into an in-flight turn. The call is wrapped with protocol-integrity checks on entry and exit.","triggerScenarios":"Calling steer() while a turn is running on a session whose driver lacks a steer implementation; steering a driver/adapter that never supported mid-turn steering (session.steer undefined).","commonSituations":"Using an agent adapter (e.g., a non-interactive CLI driver) that cannot accept input mid-run; steering before upgrading to a driver version with steer support; UI sending a steer action for an agent type that only accepts turn-boundary messages.","solutions":["Verify the driver implements steer before enabling steering in the UI/CLI for that agent type","Upgrade the adapter/driver to a version with steer support","Queue the message and deliver it as the next turn's user message instead of steering","Feature-detect: if (!session.steer) fall back to interrupt-then-send"],"exampleFix":"// before\nawait backend.steer({ turnId, message });\n// after\nif (!backend.canSteer()) {\n  await backend.interrupt({ reason: 'pending-steer' });\n  await backend.send({ message });\n} else {\n  await backend.steer({ turnId, message });\n}","handlingStrategy":"try-catch","validationCode":"if (typeof session.steer !== 'function') throw new Error('steering not supported by this driver');","typeGuard":"const canSteer = (s: HarnessSession): s is HarnessSession & { steer: NonNullable<HarnessSession['steer']> } => typeof s.steer === 'function';","tryCatchPattern":"try { await backend.steer({ turnId, message }); } catch (e) { if (e.message === 'steering is unavailable') { queueForNextTurn(message); } else throw e; }","preventionTips":["Gate steering UI on driver capability","Upgrade adapters that lack steer support","Fall back to interrupt + resend when steering is absent"],"tags":["steering","capability-missing","session"],"backgroundTag":"unsupported-operation","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}