paperclipai/paperclip · error · Error

That file is empty. Choose the private key downloaded from…

Error message

That file is empty. Choose the private key downloaded from your GitHub App.

What it means

readGitHubPrivateKeyFile validates the file the user selected for a GitHub App private key before reading it. A file whose `size` is exactly 0 cannot be a valid .pem key, so the function throws immediately. This check runs before file.text() so empty selections fail fast with actionable copy.

Solutions

  1. Re-download the private key from the GitHub App settings page (Developper settings > GitHub Apps > your app > Private key > Generate) and select the new .pem file.
  2. Check the file in the picker handler and reject zero-byte files with a clear message before calling the reader.
  3. If constructing a File in tests or code, include actual PEM content so size > 0.
  4. Fall back to the paste-private-key textarea option instead of file upload.

Example fix

// before
const [file] = e.target.files;
await readGitHubPrivateKeyFile(file);

// after
const [file] = e.target.files;
if (file.size === 0) {
  setError("That file is empty. Re-download your GitHub App private key (.pem).");
  return;
}
await readGitHubPrivateKeyFile(file);
Defensive patterns

Strategy: validation

Validate before calling

if (file.size === 0) { showError("That file is empty. Choose the private key downloaded from your GitHub App."); return; }

Type guard

const isNonEmptyFile = (f: Pick<File, "size">): boolean => f.size > 0;

Try / catch

try {
  const key = await readGitHubPrivateKeyFile(file);
} catch (err) {
  if (err instanceof Error && err.message.includes("empty")) {
    showError(err.message);
  } else { throw err; }
}

Prevention

When it happens

Trigger: User selects a 0-byte file in the GitHub App setup file input (e.g. an interrupted download or an empty placeholder file); a programmatically constructed File/Blob with size 0 is passed to `privateKey` -> readGitHubPrivateKeyFile.

Common situations: Browser download of the GitHub App .pem was interrupted leaving a zero-byte file; user picked the wrong (empty) file in the picker; automated test passes `new File([], "key.pem")` which has size 0.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/c77adc3ff6c41271. Report an issue: GitHub.

Appendix: source

Thrown at ui/src/pages/apps/chat/github-private-key-file.ts:23

  return {
    start() {
      revision += 1;
      return revision;
    },
    invalidate() {
      revision += 1;
    },
    isCurrent(candidate: number) {
      return candidate === revision;
    },
  };
}

export async function readGitHubPrivateKeyFile(
  file: Pick<File, "size" | "text">,
): Promise<string> {
  if (file.size === 0) {
    throw new Error(
      "That file is empty. Choose the private key downloaded from your GitHub App.",
    );
  }
  if (file.size > GITHUB_PRIVATE_KEY_FILE_MAX_BYTES) {
    throw new Error(
      "That file is too large. Choose a GitHub App private key smaller than 64 KB.",
    );
  }

  let value: string;
  try {
    value = await file.text();
  } catch {
    throw new Error(
      "Paperclip couldn't read that file. Choose the .pem file again or paste the private key.",
    );
  }
  if (!value.trim()) {

View on GitHub (pinned to 3f1d897a7c)