decolua/9router · error
scopes is required
Error message
scopes is required
What it means
A non-empty scopes (or scope) value is required — the OAuth scope string sent with refresh requests and persisted in providerSpecificData. Accepts an array of strings or a single space-separated string; it must normalize to something non-empty.
Source
Thrown at src/lib/oauth/kiroExternalIdp.js:107
}
const authMethod = normalizeString(input.auth_method || input.authMethod);
if (authMethod && authMethod !== "external_idp") {
throw new Error("Only external_idp Kiro auth is supported by this importer");
}
const accessToken = normalizeString(input.access_token || input.accessToken);
const refreshToken = normalizeString(input.refresh_token || input.refreshToken);
const clientId = normalizeString(input.client_id || input.clientId);
const tokenEndpoint = validateMicrosoftTokenEndpoint(input.token_endpoint || input.tokenEndpoint);
const profileArn = normalizeString(input.profile_arn || input.profileArn);
const region = normalizeString(input.region) || DEFAULT_REGION;
const scope = normalizeScope(input.scopes || input.scope);
if (!accessToken) throw new Error("access_token is required");
if (!refreshToken) throw new Error("refresh_token is required");
if (!clientId) throw new Error("client_id is required");
if (!scope) throw new Error("scopes is required");
if (!profileArn) throw new Error("profile_arn is required");
const payload = decodeJwtPayload(accessToken);
const email = input.email || payload?.email || payload?.preferred_username || payload?.upn || payload?.sub || null;
return {
accessToken,
refreshToken,
expiresAt: resolveExpiresAt(input),
email,
providerSpecificData: {
profileArn,
region,
authMethod: "external_idp",
provider: "CLIProxyAPI",
clientId,
tokenEndpoint,
scope,View on GitHub (pinned to 90b52e06ff)
Solutions
- Add scopes with the space-separated scope string used by the login (e.g. 'openid profile email offline_access')
- If passing an array, ensure at least one non-empty string element
- Match the scopes exactly to what the original token was issued with — mismatched scopes can make refresh fail upstream
- Rename the key to scopes or scope in your auth document
Example fix
// before
{ "access_token": "...", "refresh_token": "...", "client_id": "..." }
// after
{ "access_token": "...", "refresh_token": "...", "client_id": "...", "scopes": "openid profile email offline_access" } Defensive patterns
Strategy: validation
Validate before calling
const sc = auth.scopes ?? auth.scope;
const normalized = Array.isArray(sc)
? sc.filter(s => typeof s === 'string' && s.trim()).join(' ')
: (typeof sc === 'string' ? sc.trim() : '');
if (!normalized) throw new Error('scopes missing or empty in Kiro auth'); Type guard
function hasScopes(a) {
const s = a?.scopes ?? a?.scope;
if (Array.isArray(s)) return s.some(x => typeof x === 'string' && x.trim());
return typeof s === 'string' && s.trim() !== '';
} Try / catch
try {
normalizeKiroExternalIdpAuth(auth);
} catch (e) {
if (e.message === 'scopes is required') {
console.error('Add the OAuth scopes used at login, e.g. "openid profile email offline_access"');
}
throw e;
} Prevention
- Store scopes exactly as issued at login so refresh requests match the original grant
- Filter empty strings out of scope arrays before import
- Use 'scopes' or 'scope' as the key — other names are ignored
- Include offline_access in scopes if you need refresh tokens at all
When it happens
Trigger: Auth JSON missing scopes/scope, scopes: [], scopes: [""], or scopes: " " — normalizeScope returns an empty string and the guard throws.
Common situations: Hand-built auth JSON omitting scopes; an array containing only empty strings; a tool exporting scope under a different key (e.g. 'scope_list') the importer doesn't read.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- Zed callback must include user_id and access_token
- access_token is required
- refresh_token is required
- Missing Zed callback URL
- Invalid Zed callback URL
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/7bcaf209ad6009ee.
Report an issue: GitHub.