decolua/9router · error · Error
cosy: user id is empty
Error message
cosy: user id is empty
What it means
buildCosyHeaders signs every Cosy/Qoder request with credentials that must include a userId. The function throws immediately when creds.userId is missing or empty, before computing the encrypted header payload. This is a credential-completeness guard: signed requests cannot be constructed without a user identity.
Source
Thrown at open-sse/shared/qoder/cosy.js:117
return uuidv4();
}
/**
* Build the full Cosy-* header set for a single Qoder request.
*
* @param {Buffer|Uint8Array|string} body The exact bytes that will be sent.
* For GET requests pass an empty Buffer / "".
* @param {string} requestUrl Full request URL (used for sigPath).
* @param {object} creds
* @param {string} creds.userId Stable Qoder user id.
* @param {string} creds.authToken Device access token (`dt-...`).
* @param {string} [creds.name] Display name (optional).
* @param {string} [creds.email] Email (optional, can be empty).
* @param {string} [creds.machineId] Persisted machine UUID.
* @returns {Record<string, string>} Header map ready to merge onto fetch().
*/
export function buildCosyHeaders(body, requestUrl, creds) {
if (!creds?.userId) throw new Error("cosy: user id is empty");
if (!creds?.authToken) throw new Error("cosy: auth token is empty");
const bodyBuf = Buffer.isBuffer(body)
? body
: typeof body === "string"
? Buffer.from(body, "latin1")
: Buffer.from(body || []);
const { cosyKey, info } = encryptUserInfo({
uid: creds.userId,
security_oauth_token: creds.authToken,
name: creds.name || "",
aid: "",
email: creds.email || "",
});
const timestamp = String(Math.floor(Date.now() / 1000));
const requestId = uuidv4();View on GitHub (pinned to 90b52e06ff)
Solutions
- Complete the Cosy login flow so both userId and authToken are persisted on the account
- Inspect the stored account record and backfill the missing userId
- Re-authenticate the Qoder/Cosy provider from the dashboard to rewrite credentials
- Check field naming — ensure the code reads creds.userId and the storage layer uses the same key
Example fix
// before
const headers = buildCosyHeaders(body, url, { authToken: account.token });
// after
const headers = buildCosyHeaders(body, url, { authToken: account.token, userId: account.userId }); Defensive patterns
Strategy: validation
Validate before calling
function canBuildCosyHeaders(creds) {
return Boolean(creds?.userId && creds?.authToken);
}
if (!canBuildCosyHeaders(creds)) await ensureCosyLogin(account); Type guard
function hasCosyUserId(c) { return typeof c?.userId === "string" && c.userId.length > 0; } Try / catch
try {
headers = buildCosyHeaders(body, url, creds);
} catch (e) {
if (/user id is empty/.test(e.message)) {
await reloginCosy(account);
headers = buildCosyHeaders(body, url, refreshedCreds);
} else throw e;
} Prevention
- Persist userId together with authToken in one transaction
- Validate both fields before every Cosy request
- Re-auth when either field is missing or empty
- Keep field names consistent between storage and creds mapping
When it happens
Trigger: Executing a Cosy request (via execute or headers helpers) with creds = { authToken: '...' } but no userId, or userId = '' after a partial login/parse of the account record.
Common situations: OAuth/login flow stored the authToken but failed to persist userId; account imported by pasting only a token; DB record fields renamed so userId is read from the wrong key; migration dropping the column.
Related errors
- cosy: auth token is empty
- qoder PAT exchange failed: ${res.status} ${text.slice(0, 200
- No Codex access token available. Please re-authorize the con
- aes key must be 16 bytes, got ${keyBytes.length}
- Zed credential is missing userId or accessToken
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/cf486bd2e2870249.
Report an issue: GitHub.