can1357/oh-my-pi · error · AIError.ProviderResponseError
Devin AssignModel error: response carried no assignment JWT
Error message
Devin AssignModel error: response carried no assignment JWT and model uid
What it means
Thrown by assignDevinModel when AssignModel returns HTTP 200 but the decoded AssignModelResponse is missing either assignmentJwt or modelUid. Without both, the library cannot authenticate the subsequent stream against the assigned model, so it fails fast with a ProviderResponseError (kind: runtime).
Source
Thrown at packages/ai/src/providers/devin.ts:559
method: "POST",
headers: {
"content-type": "application/proto",
"connect-protocol-version": "1",
accept: "*/*",
},
body: toBinary(AssignModelRequestSchema, request),
signal,
});
const payload = new Uint8Array(await response.arrayBuffer());
if (!response.ok) {
throw new AIError.DevinApiError(
`Devin AssignModel error ${response.status} ${response.statusText}: ${new TextDecoder().decode(payload)}`,
response.status,
);
}
const assignment = decodeDevinUnaryMessage(AssignModelResponseSchema, payload)?.assignment;
if (!assignment?.assignmentJwt || !assignment.modelUid) {
throw new AIError.ProviderResponseError(
"Devin AssignModel error: response carried no assignment JWT and model uid",
{ provider: model.provider, kind: "runtime" },
);
}
logger.debug("devin: router assigned a model", {
router: model.requestModelId ?? model.id,
assigned: assignment.modelUid,
});
return assignment;
}
/**
* The prompt the router scores: the current user/developer turn on its own.
* Native leaves `messageId` empty here — the id for the turn is minted by the
* chat request that follows.
*/
function buildRouterPrompt(messages: Message[]): ChatMessagePrompt | undefined {
for (let index = messages.length - 1; index >= 0; index--) {View on GitHub (pinned to 9690622007)
Solutions
- Retry the request — transient empty assignments often succeed on a second attempt
- Confirm the account has entitlements for the requested model on the Devin instance
- Update pi-ai if the Devin server's AssignModelResponse schema has changed
- Inspect Devin instance logs to see why the assignment came back incomplete
Defensive patterns
Strategy: retry
Validate before calling
// Verify entitlement before assigning:
const entitled = await fetch(`${devinBaseUrl}/entitlements`, { headers: { authorization: `Bearer ${jwt}` } }).then(r => r.json());
if (!entitled.models?.includes(modelUid)) throw new Error(`Account lacks entitlement for ${modelUid}`); Type guard
function hasAssignment(v: unknown): v is { assignmentJwt: string; modelUid: string } {
if (typeof v !== "object" || v === null) return false;
const a = v as { assignmentJwt?: unknown; modelUid?: unknown };
return typeof a.assignmentJwt === "string" && a.assignmentJwt.length > 0 && typeof a.modelUid === "string" && a.modelUid.length > 0;
} Try / catch
try {
const assignment = await assignDevinModel(model, request, signal);
} catch (err) {
if (err instanceof AIError.ProviderResponseError && err.message.includes("no assignment JWT")) {
await Bun.sleep(500);
return assignDevinModel(model, request, signal); // retry once for transient empty assignments
}
throw err;
} Prevention
- Confirm model entitlements on the Devin account before automation
- Retry once on empty assignment responses — often a server-side race
- Keep the client's AssignModel proto in sync with your Devin server version
- Alert on repeated partial AssignModel responses; they signal service degradation
When it happens
Trigger: Devin accepts the assignment request but the response's assignment field is absent or partially populated — server-side assignment race, account without model entitlements, or proto schema drift between client and server.
Common situations: Devin router returned an empty/partial assignment during a load or outage; user account lacking entitlement to the requested model; Devin server version mismatch with the bundled protobuf definitions.
Related errors
- Devin auth error: GetUserJwt returned an empty user JWT
- Devin API error: response body is empty
- Devin AssignModel error ${response.status} ${response.status
- Devin API error ${response.status} ${response.statusText}: $
- Devin Connect frame length ${len} exceeds ${MAX_CONNECT_FRAM
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/7613ec966b01371b.
Report an issue: GitHub.