jackwener/OpenCLI · error · ConfigError

Failed to parse Xiaoyuzhou credential file: ${filePath}

Error message

Failed to parse Xiaoyuzhou credential file: ${filePath}

What it means

When reading the xiaoyuzhou credential file fails for any reason other than the missing-token ConfigError, loadXiaoyuzhouCredentials wraps the underlying error in a ConfigError: 'Failed to parse Xiaoyuzhou credential file: <path>' with a hint to ensure the file contains valid JSON (original error appended). Typical cause: fs.readFileSync threw (permissions) or JSON.parse failed on malformed content.

Source

Thrown at clis/xiaoyuzhou/auth.js:62

        device_properties: String(raw.device_properties ?? raw.deviceProperties ?? XIAOYUZHOU_DEFAULT_DEVICE_PROPERTIES),
    };
}
export function loadXiaoyuzhouCredentials() {
    const filePath = getXiaoyuzhouCredentialFile();
    if (fs.existsSync(filePath)) {
        try {
            const parsed = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
            const credentials = normalizeXiaoyuzhouCredentials(parsed);
            if (!credentials.access_token || !credentials.refresh_token) {
                throw new ConfigError(`Xiaoyuzhou credential file is missing access_token or refresh_token: ${filePath}`, 'Recreate the file with valid credentials.');
            }
            return credentials;
        }
        catch (error) {
            if (error instanceof ConfigError) {
                throw error;
            }
            throw new ConfigError(`Failed to parse Xiaoyuzhou credential file: ${filePath}`, `Ensure ${filePath} contains valid JSON. (${getErrorMessage(error)})`);
        }
    }
    throw new ConfigError(`Missing Xiaoyuzhou credentials. Expected ${filePath}`, `Create ${filePath} with access_token and refresh_token.`);
}

export function saveXiaoyuzhouCredentials(credentials) {
    const filePath = getXiaoyuzhouCredentialFile();
    fs.mkdirSync(path.dirname(filePath), { recursive: true });
    fs.writeFileSync(filePath, `${JSON.stringify({
        access_token: credentials.access_token,
        refresh_token: credentials.refresh_token,
        expires_at: credentials.expires_at,
        device_id: credentials.device_id,
        device_properties: credentials.device_properties,
    }, null, 2)}\n`, 'utf-8');
}

export function shouldRefreshXiaoyuzhouCredentials(credentials, now = getNowMs()) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Validate the file: run JSON.parse on its contents (or `node -e "JSON.parse(require('fs').readFileSync('<path>','utf8'))"`) and fix the syntax error reported
  2. Recreate filePath with clean, complete JSON containing access_token and refresh_token
  3. Check file permissions/readability for the user running the CLI
  4. Read the appended getErrorMessage(error) detail in the hint to distinguish parse vs read failures

Example fix

// before (trailing comma → parse error)
{ "access_token": "abc", "refresh_token": "def", }
// after
{ "access_token": "abc", "refresh_token": "def" }
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs');
function assertValidCredJson(filePath) {
  const raw = fs.readFileSync(filePath, 'utf-8');
  try { JSON.parse(raw); } catch (e) { throw new Error(`${filePath} is not valid JSON: ${e.message}`); }
}
assertValidCredJson('./config/xiaoyuzhou.credentials.json');

Try / catch

try {
  const creds = loadXiaoyuzhouCredentials();
} catch (err) {
  if (/Failed to parse Xiaoyuzhou credential file/.test(err.message)) {
    fs.copyFileSync(credPath, credPath + '.bak');
    await regenerateCredentials(credPath); // rewrite the file as clean JSON
  } else throw err;
}

Prevention

When it happens

Trigger: Credential file contains invalid JSON (trailing commas, truncation, HTML error page pasted in); file unreadable due to permissions; encoding issues; ConfigError from the token check is intentionally rethrown unwrapped and does NOT produce this message.

Common situations: Editor saved the file as JSON5/with comments; clipboard paste captured extra text; disk-full write left a truncated file; running as a user without read access to the file.

Understand the failure class

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/558f7c7e66fd9f6d. Report an issue: GitHub.