{"record":{"id":"dde2da8d40750c3f","repo":"paperclipai/paperclip","slug":"that-file-is-too-large-choose-a-github-app-private-key","errorCode":null,"errorMessage":"That file is too large. Choose a GitHub App private key smaller than 64 KB.","messagePattern":"That file is too large\\. Choose a GitHub App private key smaller than 64 KB\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ui/src/pages/apps/chat/github-private-key-file.ts","lineNumber":28,"sourceCode":"    invalidate() {\n      revision += 1;\n    },\n    isCurrent(candidate: number) {\n      return candidate === revision;\n    },\n  };\n}\n\nexport async function readGitHubPrivateKeyFile(\n  file: Pick<File, \"size\" | \"text\">,\n): Promise<string> {\n  if (file.size === 0) {\n    throw new Error(\n      \"That file is empty. Choose the private key downloaded from your GitHub App.\",\n    );\n  }\n  if (file.size > GITHUB_PRIVATE_KEY_FILE_MAX_BYTES) {\n    throw new Error(\n      \"That file is too large. Choose a GitHub App private key smaller than 64 KB.\",\n    );\n  }\n\n  let value: string;\n  try {\n    value = await file.text();\n  } catch {\n    throw new Error(\n      \"Paperclip couldn't read that file. Choose the .pem file again or paste the private key.\",\n    );\n  }\n  if (!value.trim()) {\n    throw new Error(\n      \"That file is empty. Choose the private key downloaded from your GitHub App.\",\n    );\n  }\n  return value;","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/ui/src/pages/apps/chat/github-private-key-file.ts#L10-L46","documentation":"readGitHubPrivateKeyFile enforces a maximum file size of GITHUB_PRIVATE_KEY_FILE_MAX_BYTES (64 KB, matching GitHub's actual key size). GitHub App private keys are small PEM files (~1-2 KB); anything larger is almost certainly the wrong file, so the reader throws rather than reading it.","triggerScenarios":"User selects a file larger than 64 KB in the GitHub private key picker — e.g. a bundle, a certificate chain, a screenshot-named .pem, or a combined key archive; passing an oversized Blob/File programmatically via the `privateKey` caller.","commonSituations":"User confuses the .pem private key with a larger downloaded credentials zip or an SSH key with a long comment; user selects their app's public cert or an old exported bundle; dragging the wrong file from the Downloads folder.","solutions":["Select the actual .pem file downloaded from GitHub App settings (should be ~2 KB, starts with '-----BEGIN RSA PRIVATE KEY-----').","Open the file in a text editor to confirm it is a PEM key, not a zip/binary; re-generate the key if needed.","Check the file size in the input handler and warn before invoking the reader.","Paste the key text directly into the provided textarea instead of file upload."],"exampleFix":"// before\nawait readGitHubPrivateKeyFile(file);\n\n// after\nif (file.size > 64 * 1024) {\n  setError(\"Choose a GitHub App private key (.pem) smaller than 64 KB.\");\n  return;\n}\nawait readGitHubPrivateKeyFile(file);","handlingStrategy":"validation","validationCode":"if (file.size > 64 * 1024) { showError(\"That file is too large. Choose a GitHub App private key smaller than 64 KB.\"); return; }","typeGuard":"const isPlausibleKeySize = (f: Pick<File, \"size\">): boolean => f.size > 0 && f.size <= 64 * 1024;","tryCatchPattern":"try {\n  const key = await readGitHubPrivateKeyFile(file);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"too large\")) {\n    showError(\"Please select the .pem private key, not a bundle or zip.\");\n  } else { throw err; }\n}","preventionTips":["Accept only .pem extensions in the file picker (accept=\".pem\")","Warn users the key is a small text file (~2 KB)","Provide a paste fallback for large/wrong selections","Verify file head contains '-----BEGIN' before submit"],"tags":["file-upload","validation","file-size","github-app"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-22T06:17:15.046Z"}