jackwener/OpenCLI · error · CommandExecutionError
Xiaoyuzhou API rejected the credentials with service code ${
Error message
Xiaoyuzhou API rejected the credentials with service code ${numericCode} What it means
When the Xiaoyuzhou API envelope returns service code 401 or 403, the CLI raises an authentication error via createXiaoyuzhouAuthError, indicating the stored credentials (token/cookies) were rejected. This distinguishes auth failures from generic service errors so users know to re-authenticate.
Source
Thrown at clis/xiaoyuzhou/auth.js:243
}
let parsed;
try {
parsed = JSON.parse(bodyText);
}
catch (error) {
throw new CommandExecutionError(`Xiaoyuzhou API returned invalid JSON: ${getErrorMessage(error)}`);
}
const serviceCode = parsed?.code;
if (serviceCode !== undefined && serviceCode !== null) {
const numericCode = Number(serviceCode);
if (!Number.isFinite(numericCode)) {
throw new CommandExecutionError('Xiaoyuzhou API returned an invalid service code');
}
if (numericCode === 401 || numericCode === 403) {
throw createXiaoyuzhouAuthError(`Xiaoyuzhou API rejected the credentials with service code ${numericCode}`);
}
if (numericCode !== 0 && numericCode !== 200) {
throw new CommandExecutionError(
parsed?.message || parsed?.msg || `Xiaoyuzhou API returned service code ${numericCode}`,
);
}
}
if (parsed?.success === false) {
throw new CommandExecutionError(parsed?.message || parsed?.msg || 'Xiaoyuzhou API returned success=false');
}
return {
credentials,
raw: parsed,
data: parsed?.data,
};
}
export async function fetchXiaoyuzhouTranscriptBody(url, fetchImpl = fetch) {
let response;
try {
response = await fetchImpl(url, {View on GitHub (pinned to 49907e53dc)
Solutions
- Re-authenticate: run the xiaoyuzhou auth/login flow to obtain fresh credentials, then retry.
- Inspect stored credentials (token/cookies file) for truncation or staleness; replace them wholesale.
- Verify the Authorization header/cookies are actually attached to the outgoing request.
- If 403 persists with valid creds, check for account-level blocks (bans, region restrictions) or IP-based rate limiting.
Example fix
// before: retrying with stale creds
const data = await requestXiaoyuzhouJson(credentials, '/episode/xyz', ...);
// after: catch auth error and re-auth once
try {
data = await requestXiaoyuzhouJson(credentials, '/episode/xyz', ...);
} catch (e) {
if (isXiaoyuzhouAuthError(e)) {
credentials = await refreshXiaoyuzhouCredentials();
data = await requestXiaoyuzhouJson(credentials, '/episode/xyz', ...);
} else throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// before calls: fail fast if credentials are missing/stale
if (!credentials || !credentials.token || (credentials.expiresAt && Date.now() >= credentials.expiresAt)) {
credentials = await refreshXiaoyuzhouCredentials(); // re-auth before hitting the API
} Type guard
function isXiaoyuzhouAuthError(e) {
return e instanceof CommandExecutionError && /rejected the credentials with service code (401|403)/.test(e.message);
} Try / catch
try {
return await requestXiaoyuzhouJson(creds, path, params);
} catch (e) {
if (isXiaoyuzhouAuthError(e)) {
const fresh = await reauthenticateXiaoyuzhou();
return await requestXiaoyuzhouJson(fresh, path, params); // retry once with new creds
}
throw e;
} Prevention
- Store the token's expiry and refresh proactively before it lapses.
- Wrap all xiaoyuzhou calls in one helper that auto-reauths once on 401/403.
- Never hand-edit credential files; always use the auth flow to regenerate them.
- Check machine clock sync if tokens are time-based.
- Keep cookie/auth headers complete — copying partial values is a common cause.
When it happens
Trigger: Any requestXiaoyuzhouJson call (result, response, historyResponse, progressResponse, episodeResponse, transcriptResponse) where parsed.code is 401 or 403 — expired auth token, revoked session, missing/invalid Authorization header or cookies, or banned account.
Common situations: Token expired after the session lifetime passed; user logged out elsewhere invalidating the token; copied cookie/auth header incomplete or from a different account; clock skew invalidating signed tokens; account rate-limited into a 403.
Related errors
- ${label} returned HTTP ${resp.status}: ${summarizeApiError(p
- LinkedIn messaging API authentication failed:
- ${result.message || result.error || 'API 请求失败'}
- FETCH_ERROR
- FETCH_ERROR
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/5bf5d80f2839d58c.
Report an issue: GitHub.