different-ai/openwork · error · EnvStoreReadError

Environment variable store could not be read

Error message

Environment variable store could not be read

What it means

readStore reads the env-var store file and throws EnvStoreReadError when the file exists but cannot be read (any error other than ENOENT), or when tolerateInvalid is false and callers should not silently get an empty store.

Source

Thrown at apps/server/src/env-file.ts:88

function emptyStore(): EnvStoreFile {
  return { schemaVersion: 1, updatedAt: Date.now(), variables: [] };
}

async function readStore(
  path: string,
  options: { tolerateInvalid?: boolean } = {},
): Promise<EnvStoreFile> {
  if (!(await exists(path))) {
    return emptyStore();
  }
  let raw = "";
  try {
    raw = await readFile(path, "utf8");
  } catch (error) {
    if ((error as { code?: string }).code === "ENOENT") return emptyStore();
    if (options.tolerateInvalid) return emptyStore();
    throw new EnvStoreReadError("Environment variable store could not be read");
  }

  let parsed: Partial<EnvStoreFile>;
  try {
    parsed = JSON.parse(raw) as Partial<EnvStoreFile>;
  } catch {
    if (options.tolerateInvalid) return emptyStore();
    throw new EnvStoreReadError("Environment variable store is invalid JSON");
  }

  if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.variables)) {
    if (options.tolerateInvalid) return emptyStore();
    throw new EnvStoreReadError("Environment variable store has an invalid format");
  }

  const variables = parsed.variables
    .map(parseRecord)
    .filter((entry): entry is EnvRecord => Boolean(entry));

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Check file permissions on the env store file and fix ownership/chmod so the server process can read it
  2. Verify the configured store path points at a regular file, not a directory
  3. If the data is disposable, delete the corrupted/unreadable file so the next read creates a fresh store (ENOENT path)
  4. Run the server with the same user that owns the store file

Example fix

// before
store.json -> owned by root, mode 600, server runs as "app"
// after
sudo chown app:app store.json && chmod 600 store.json
Defensive patterns

Strategy: fallback

Validate before calling

try { await stat(path); } catch (e) { if (e.code !== "ENOENT") warn("store file unreadable: " + e.code); }

Try / catch

try { return await readStore(path, { tolerateInvalid: false }); } catch { return { variables: [] }; }

Prevention

When it happens

Trigger: ensureLoaded/store call readStore while the store file exists but is unreadable: permission denied, EACCES, EISDIR (path is a directory), or an I/O error; ENOENT is tolerated (returns empty store).

Common situations: Store file created by another user/root with restrictive permissions; wrong path configured pointing at a directory; disk I/O failure; read-only filesystem mount.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/af8b56189b0399c7. Report an issue: GitHub.