deepseek-ai/deepseek-harness · error · TypertGatewayError
context-unavailable
context-unavailable
Error message
Context provider ${JSON.stringify(marker.invocation.context)} is unavailable What it means
Thrown while the Gateway derives a weak (SRC-marker) invocation descriptor: the Remote method marker declares a context-scoped receiver (invocation.kind === 'context'), but typert.contexts.getHost() finds no Host Context provider registered under the marker's context key. Without that provider the Gateway cannot map a wire identity to the scoped Cordis Context the method must run in, so it refuses to build the descriptor before any request validation happens.
Source
Thrown at packages/api/gateway/src/index.ts:324
codec: { mode: 'src-json' },
}
if (wires.has(parameter.wire)) {
throw new TypertGatewayError(
'signature-invalid',
endpoint,
`multiple parameters use wire field ${JSON.stringify(parameter.wire)}`,
{ field: parameter.wire },
)
}
wires.add(parameter.wire)
parameters.push(parameter)
}
let receiver: InvocationDescriptor['invocation'] = { kind: 'direct' }
if (marker.invocation.kind === 'context') {
const provider = this.ctx.typert.contexts.getHost(marker.invocation.context)
if (provider === undefined) {
throw new TypertGatewayError(
'context-unavailable',
endpoint,
`Context provider ${JSON.stringify(marker.invocation.context)} is unavailable`,
)
}
if (wires.has(provider.wire)) {
throw new TypertGatewayError(
'signature-invalid',
endpoint,
`Context identity conflicts with wire field ${JSON.stringify(provider.wire)}`,
{ field: provider.wire },
)
}
receiver = {
kind: 'context',
context: marker.invocation.context,
wire: provider.wire,
codec: { mode: 'src-json' },View on GitHub (pinned to b150a551b8)
Solutions
- Add the plugin that registers the Host Context provider for the key shown in the message (the JSON.stringify'd value is the exact registry key) to the same composition as the Remote exporter.
- Verify the registerHost key string matches the merge-declared TypertContextMap key exactly, including spelling and case.
- If the provider was disposed by HMR or a plugin reload, restart the host process so registration is fresh.
- If the method should not be context-scoped, remove the context invocation from its Remote marker so the receiver resolves directly.
Example fix
# before — remote exporter mounted, context provider missing
plugins:
- dsh-session-remotes
# after — plugin owning the 'session' Host Context loads too
plugins:
- dsh-session # calls typert.contexts.registerHost('session', provider)
- dsh-session-remotes Defensive patterns
Strategy: validation
Validate before calling
import type { Context } from '@deepseek-ai/cordis'
// Fail at composition/boot time instead of at first RPC.
function assertHostContext(ctx: Context, key: string): void {
if (ctx.typert.contexts.getHost(key) === undefined) {
throw new Error(`Host Context provider "${key}" is not registered; load its owning plugin before mounting remotes`)
}
} Type guard
import { TypertGatewayError } from '@deepseek-ai/dsh-api-gateway'
function isContextUnavailable(error: unknown): error is TypertGatewayError {
return error instanceof TypertGatewayError && error.code === 'context-unavailable'
} Try / catch
try {
await gateway.invoke({ namespace: 'session:chat', method: 'send', args: { sessionId, text } })
} catch (error) {
if (error instanceof TypertGatewayError && error.code === 'context-unavailable') {
// composition defect, not request state: surface as setup error, never retry
throw new Error(`host misconfigured: ${error.message}`)
}
throw error
} Prevention
- Mount Remote exporters only in compositions that also load the plugin calling typert.contexts.registerHost for every context kind those exporters use.
- Keep the merge-declared TypertContextMap key in one shared module imported by both the marker declaration and the registerHost call so the strings cannot drift.
- Add a boot assertion that walks every mounted context-scoped endpoint and checks typert.contexts.getHost before the Connection starts serving.
When it happens
Trigger: Any dispatch (direct typertGateway.invoke or a Connection RPC) to an endpoint whose Service marker declares a context-scoped method while the plugin that calls typert.contexts.registerHost(<key>, provider) for that context kind is not active — e.g. calling a 'session:<ns>/<method>' scoped remote on a host that never loaded the plugin providing the 'session' Host Context.
Common situations: cordis.yml loads the Remote-exporting plugin but omits the plugin owning the scoped Context; the provider plugin was disposed or reloaded via HMR; the merge-declared TypertContextMap key was renamed on one side (marker or registerHost) so the strings no longer match.
Related errors
AI-assisted analysis of deepseek-ai/deepseek-harness@b150a551b8 (2026-08-24).
Data as JSON: /api/errors/231227477ed479c1.
Report an issue: GitHub.