yamadashy/repomix · error · RepomixError

Could not read the remote repository's config (${configName}

Error message

Could not read the remote repository's config (${configName}) for review: ${error instanceof Error ? error.message : String(error)}

What it means

confirmRemoteConfigTrust must display the remote repo's config bytes to the user before asking for trust. If fs.readFile of the resolved config path fails for any reason (permission denied, file deleted between discovery and read, I/O error), the original error is wrapped in a RepomixError that names the config file and includes the underlying error message. This happens after the containment check has passed, so the file existed at lstat time.

Source

Thrown at src/cli/prompts/remoteConfigTrustPrompt.ts:193

      ),
    );
    return;
  }

  // Non-interactive (CI, pipes): keep the historical non-prompting behavior so
  // existing --remote-trust-config automations do not hang. Announce it on stderr.
  if (!deps.isInteractive()) {
    writeErr(
      pc.dim(`Trusting remote config non-interactively: ${configName} (${sanitizeForDisplay(redactUrl(repoUrl))})`),
    );
    return;
  }

  let configBytes: Buffer;
  try {
    configBytes = await deps.readFile(configPath);
  } catch (error) {
    throw new RepomixError(
      `Could not read the remote repository's config (${configName}) for review: ${
        error instanceof Error ? error.message : String(error)
      }`,
    );
  }
  // Pin the raw bytes, not the decoded text. Decoding as UTF-8 maps every invalid
  // sequence to U+FFFD, so two different files can decode to the same string; a repo
  // could then swap in a config the user never approved and still match the stored
  // digest. Code configs are loaded from bytes by jiti, so the bytes are what runs.
  const configDigest = sha256(configBytes);
  const configText = configBytes.toString('utf8');

  // Already trusted for this exact config content.
  if (await deps.isRemoteConfigTrusted(repoUrl, configDigest)) return;

  // The menu renders on stdout. Under --stdout the packed output goes there too and
  // the two collide; if stdout is redirected or piped the menu is invisible and we
  // would block on a keypress nobody can see. Refuse in both cases rather than

View on GitHub (pinned to f465ad9093)

Solutions

  1. Read the wrapped inner message to identify the cause (EACCES, ENOENT, EIO) and fix that underlying condition.
  2. Re-run the command — temp-dir races are often transient and the clone is recreated fresh.
  3. Check permissions on the clone directory (under your TMPDIR) and any security software that may quarantine files there.
  4. If the repo's config is unreadable or unstable, skip it with an explicit local `--config /path/to/your.config.json`.
Defensive patterns

Strategy: try-catch

Validate before calling

import fs from 'node:fs/promises';
try {
  await fs.access(configPath, fs.constants.R_OK);
} catch (e) {
  console.error(`Config ${configPath} is not readable: ${(e as Error).message}`);
}

Try / catch

try {
  await confirmRemoteConfigTrust(options);
} catch (e) {
  if (e instanceof RepomixError && e.message.startsWith('Could not read the remote repository\'s config')) {
    console.error('Config unreadable in clone; retrying or using --config instead.');
  } else throw e;
}

Prevention

When it happens

Trigger: The config file found by findLocalConfigPath inside the freshly cloned repo cannot be read by deps.readFile — e.g. permissions changed, the file was removed by a concurrent process, a race with cleanup of the temp clone dir, or an OS-level I/O failure. Occurs during `repomix --remote <url>` when the interactive trust path is taken.

Common situations: Another process or antivirus deletes/quarantines files in the temp clone directory mid-run; restrictive umask or ACLs make the file unreadable; disk errors; TOCTOU races in shared temp directories.

Related errors


AI-assisted analysis of yamadashy/repomix@f465ad9093 (2026-08-29). Data as JSON: /api/errors/ee1796c409f1f803. Report an issue: GitHub.