coleam00/Archon · error

Pi auth storage init failed: ${e.message}. Check that ~/.pi/

Error message

Pi auth storage init failed: ${e.message}. Check that ~/.pi/agent/auth.json (or $PI_CODING_AGENT_DIR/auth.json) is valid JSON and readable.

What it means

sendQuery constructs a Pi ModelRuntime backed by the auth storage (~/.pi/agent/auth.json or $PI_CODING_AGENT_DIR/auth.json). If that construction throws (malformed JSON, unreadable file, bad permissions), the error is rethrown with guidance pointing at the auth file, preserving the original message and logging pi.auth_storage_init_failed.

Source

Thrown at packages/providers/src/community/pi/provider.ts:465

      // there first and fall back to process.env for a shell-level override.
      const archonAuthPath =
        (requestOptions?.env?.ARCHON_PI_AUTH_PATH ?? process.env.ARCHON_PI_AUTH_PATH)?.trim() ||
        undefined;
      // pi-coding-agent 0.84.0 folded AuthStorage + ModelRegistry into a single
      // ModelRuntime; ModelRegistry is now a thin facade constructed from a
      // runtime. authPath still feeds the file-backed CredentialStore inside
      // ModelRuntime — the per-user auth.json path is honoured the same way.
      // modelsPath follows the same per-call pattern for custom providers'
      // `${VAR}` substitution.
      modelRuntime = await piCodingAgent.ModelRuntime.create({
        authPath: archonAuthPath,
        ...(customProviderModelsPath ? { modelsPath: customProviderModelsPath } : {}),
      });
      modelRegistry = new piCodingAgent.ModelRegistry(modelRuntime);
    } catch (err) {
      const e = err as Error;
      getLog().error({ err: e, piProvider: parsed.provider }, 'pi.auth_storage_init_failed');
      throw new Error(
        `Pi auth storage init failed: ${e.message}. Check that ~/.pi/agent/auth.json ` +
          '(or $PI_CODING_AGENT_DIR/auth.json) is valid JSON and readable.'
      );
    } finally {
      // The per-call models.json holds the literal substituted secret in
      // cleartext. ModelRuntime.create reads it once at construction (via
      // ModelConfig.load); the runtime carries the loaded values for the
      // rest of the session, so the file can be removed as soon as the
      // create() promise resolves. Without this cleanup, long-running
      // processes accumulate one file per sendQuery and eventually hit
      // ENOSPC, after which buildCustomProviderModelsPath's mkdirSync fails
      // and the SDK silently falls through to the unsubstituted user
      // models.json — re-opening the round-1 R1 leak surface. Errors here
      // are non-fatal (the file may already be gone, or the FS may be in
      // an odd state); the original error has already been surfaced.
      if (customProviderModelsPath) {
        try {
          rmSync(customProviderModelsPath, { force: true });

View on GitHub (pinned to 0773b97458)

Solutions

  1. Validate ~/.pi/agent/auth.json parses as JSON (e.g. `jq . ~/.pi/agent/auth.json`); fix or delete it and re-run `pi /login`
  2. Check file permissions (readable by the running user)
  3. If PI_CODING_AGENT_DIR is set, check auth.json at $PI_CODING_AGENT_DIR/auth.json instead
  4. Restore auth.json by running `pi` and `/login` to regenerate it

Example fix

// before (truncated file)
{"anthropic": {"type": "oauth", "access"
// after
$ rm ~/.pi/agent/auth.json && pi   # then /login
Defensive patterns

Strategy: try-catch

Validate before calling

import { readFileSync } from 'node:fs';
const authPath = process.env.PI_CODING_AGENT_DIR
  ? `${process.env.PI_CODING_AGENT_DIR}/auth.json` : `${process.env.HOME}/.pi/agent/auth.json`;
try {
  JSON.parse(readFileSync(authPath, 'utf8'));
} catch (e) {
  throw new Error(`Pi auth file unreadable/invalid at ${authPath}: ${e.message}; run 'pi' + /login to regenerate`);
}

Type guard

function isReadableJsonFile(path: string): boolean {
  try { JSON.parse(readFileSync(path, 'utf8')); return true; } catch { return false; }
}

Try / catch

try {
  await sendQuery(q);
} catch (err) {
  if (err.message.startsWith('Pi auth storage init failed')) {
    log.error({ cause: err }, 'pi auth file invalid; regenerating via pi /login is required');
  }
  throw err;
}

Prevention

When it happens

Trigger: sendQuery when auth.json contains invalid JSON (e.g. from a truncated write or hand edit), has wrong permissions, is a directory, or PI_CODING_AGENT_DIR points somewhere without a readable auth.json.

Common situations: Hand-editing ~/.pi/agent/auth.json and breaking JSON, syncing tools copying partial files, permissions changed by chown/chmod, or a custom PI_CODING_AGENT_DIR with a stale/invalid auth file.

Related errors


AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01). Data as JSON: /api/errors/81a368720b94ea28. Report an issue: GitHub.