anomalyco/sst · error
Missing code
Error message
Missing code
What it means
After validating grant_type, the /token endpoint requires a code form field containing the signed authorization-code JWT. If code is absent or empty, it returns HTTP 400 with "Missing code". The code is what carries the pending auth state between the authorize redirect and the token exchange.
Source
Thrown at sdk/js/src/auth/handler.ts:238
maxAge,
httpOnly: true,
...(c.req.url.startsWith("https://")
? { secure: true, sameSite: "None" }
: {}),
});
},
};
app.post("/token", async (c) => {
console.log("token request");
const form = await c.req.formData();
if (form.get("grant_type") !== "authorization_code") {
c.status(400);
return c.text("Invalid grant_type");
}
const code = form.get("code");
if (!code) {
c.status(400);
return c.text("Missing code");
}
const { payload } = await jwtVerify(
code as string,
await options.signing.publicKey()
);
if (payload.redirect_uri !== form.get("redirect_uri")) {
c.status(400);
return c.text("redirect_uri mismatch");
}
if (payload.client_id !== form.get("client_id")) {
c.status(400);
return c.text("client_id mismatch");
}
return c.json({
access_token: payload.token,View on GitHub (pinned to a0bd20f762)
Solutions
- Include the code from the authorize redirect's query string in the /token form body.
- Ensure the request body is form-encoded (URLSearchParams / application/x-www-form-urlencoded), not JSON.
- Confirm the client's redirect handler actually reads and forwards req.query.code from the callback URL.
- Log the outgoing form body before the fetch to verify all required fields (code, redirect_uri, client_id) are present.
Example fix
// before
const res = await fetch(`${authUrl}/token`, { method: "POST", body: new URLSearchParams({ grant_type: "authorization_code" }) });
// after
const code = new URL(callbackUrl).searchParams.get("code");
const res = await fetch(`${authUrl}/token`, {
method: "POST",
body: new URLSearchParams({ grant_type: "authorization_code", code: code!, redirect_uri: cb, client_id: id }),
}); Defensive patterns
Strategy: validation
Validate before calling
const code = new URL(callbackUrl).searchParams.get("code");
if (!code) throw new Error("No ?code in authorize redirect callback — cannot exchange at /token"); Type guard
function hasCode(url: string): url is string & { } {
return Boolean(new URL(url, "http://x").searchParams.get("code"));
} Try / catch
const res = await fetch(`${authUrl}/token`, { method: "POST", body });
if (res.status === 400) {
const msg = await res.text();
if (msg === "Missing code") throw new Error("Forward the code query param from the authorize redirect");
} Prevention
- Always read code from the redirect callback's query string before exchanging.
- Send form-encoded bodies (URLSearchParams), not JSON, to /token.
- Log the form body in dev to confirm code, redirect_uri, and client_id are all present.
- Handle the callback URL on the server side where query params are preserved.
When it happens
Trigger: POSTing to /token with grant_type=authorization_code but no code field in the form body, or an empty-string code (form.get("code") returns null/empty).
Common situations: A hand-written token exchange that forgot to forward the code query parameter from the authorize redirect callback; a client that drops query params when reconstructing the callback URL; sending JSON instead of form-encoded data so formData() yields no code.
Related errors
- Missing token parameter
- Invalid grant_type
- error
- Unsupported response_type: ${response_type}
- redirect_uri mismatch
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/7739a679b72848d0.
Report an issue: GitHub.