can1357/oh-my-pi · error · AIError.ProviderResponseError
Devin auth error: GetUserJwt returned an empty user JWT
Error message
Devin auth error: GetUserJwt returned an empty user JWT
What it means
Thrown by fetchDevinAuthMetadata when GetUserJwt returns HTTP 200 but the decoded GetUserJwtResponse carries no userJwt field. The server accepted the request but produced an unusable empty credential, so the library refuses to continue with a null JWT.
Source
Thrown at packages/ai/src/providers/devin.ts:512
method: "POST",
headers: {
"content-type": "application/proto",
"connect-protocol-version": "1",
accept: "*/*",
},
body: toBinary(GetUserJwtRequestSchema, request),
signal,
});
const payload = new Uint8Array(await response.arrayBuffer());
if (!response.ok) {
throw new AIError.DevinApiError(
`Devin auth error ${response.status} ${response.statusText}: ${new TextDecoder().decode(payload)}`,
response.status,
);
}
const decoded = decodeDevinUnaryMessage(GetUserJwtResponseSchema, payload);
if (!decoded?.userJwt) {
throw new AIError.ProviderResponseError("Devin auth error: GetUserJwt returned an empty user JWT", {
provider: "devin",
kind: "runtime",
});
}
const customBaseUrl = decoded.customApiServerUrl.trim();
return { userJwt: decoded.userJwt, ...(customBaseUrl ? { baseUrl: customBaseUrl.replace(/\/+$/, "") } : undefined) };
}
/**
* Resolve a server-side router (`adaptive`) into the concrete model uid plus the
* assignment JWT that authorizes it. The router uid is never a legal
* `chatModelUid`, so a failed assignment must fail the turn rather than fall
* back to sending the router id to `GetChatMessage`.
*/
async function assignDevinModel(
model: Model<"devin-agent">,
turn: DevinTurn,
baseUrl: string,View on GitHub (pinned to 9690622007)
Solutions
- Confirm the Devin account is fully provisioned and can issue user JWTs (log into the instance)
- Re-run the request — transient empty responses occasionally clear on retry
- Update pi-ai if your Devin server version changed the GetUserJwt response schema
- Check the Devin instance logs for why it returned an empty JWT
Defensive patterns
Strategy: retry
Validate before calling
// Ensure the account can mint JWTs before relying on it:
const res = await fetch(`${baseUrl}/user`, { headers: { authorization: `Bearer ${apiKey}` } });
const user = await res.json();
if (!user || user.status !== "active") throw new Error("Devin account not active — cannot obtain user JWT"); Type guard
function hasUserJwt(v: unknown): v is { userJwt: string } {
return typeof v === "object" && v !== null && typeof (v as { userJwt?: unknown }).userJwt === "string"
&& (v as { userJwt: string }).userJwt.length > 0;
} Try / catch
try {
const meta = await fetchDevinAuthMetadata(baseUrl, request, signal);
} catch (err) {
if (err instanceof AIError.ProviderResponseError && err.message.includes("empty user JWT")) {
await Bun.sleep(1000); // transient empty responses often clear
return fetchDevinAuthMetadata(baseUrl, request, signal); // retry once
}
throw err;
} Prevention
- Verify Devin account provisioning before automation runs
- Keep client proto schema in sync with the Devin server version
- Add a single retry with backoff for empty-response cases
- Monitor Devin instance logs for repeated empty JWT responses
When it happens
Trigger: Devin responds ok to GetUserJwt but the protobuf-decoded message lacks userJwt — e.g. a user account in a bad state, a server returning an empty/unpopulated response, or a server version whose response schema diverges from the bundled proto.
Common situations: Newly provisioned Devin account not yet fully initialized; Devin server version mismatch with the client's GetUserJwtRequest/Response schema; empty response from a misrouted gateway.
Related errors
- Devin AssignModel error: response carried no assignment JWT
- Devin API error: response body is empty
- Devin auth error ${response.status} ${response.statusText}:
- Failed to open auth database at '${dbPath}' after ${maxAttem
- No OAuth credential available for provider: ${provider}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/5543ab84252a6da1.
Report an issue: GitHub.