{"record":{"id":"6b2062477059b3fc","repo":"paperclipai/paperclip","slug":"paperclip-couldn-t-read-that-file-choose-the-pem-file-again","errorCode":null,"errorMessage":"Paperclip couldn't read that file. Choose the .pem file again or paste the private key.","messagePattern":"Paperclip couldn't read that file\\. Choose the \\.pem file again or paste the private key\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ui/src/pages/apps/chat/github-private-key-file.ts","lineNumber":37,"sourceCode":"export 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;\n}\n","sourceCodeStart":19,"sourceCodeEnd":48,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/ui/src/pages/apps/chat/github-private-key-file.ts#L19-L48","documentation":"When `file.text()` rejects (the browser cannot decode/read the selected file), readGitHubPrivateKeyFile converts the underlying read error into this user-facing message. It indicates the File handle is unreadable — not that the key is invalid — so it advises re-selecting the file or pasting the key.","triggerScenarios":"file.text() throws because the file was deleted/moved between selection and read; permission issues on the picked file; the browser fails to decode the file as text (binary/UTF-16 content); FileSystemFileHandle backed file is stale after a directory change.","commonSituations":"User selected the key, then deleted or re-downloaded it before submitting; picked a binary file (zip, image) that cannot be read as UTF-8 text; browser storage quota/handle invalidation after the picker returned a stale entry.","solutions":["Re-select the .pem file in the picker and submit again without moving/deleting it in between.","Open the file in a text editor to verify it is plain-text PEM; if it is binary, re-download the key from GitHub App settings.","Use the paste-private-key textarea as the fallback path.","Handle the rejection in the caller and show this message plus the paste option rather than a raw DOMException."],"exampleFix":"// before\nvalue = await file.text();\n\n// after\ntry {\n  value = await file.text();\n} catch (err) {\n  setError(\"Paperclip couldn't read that file. Choose the .pem file again or paste the private key.\");\n  return;\n}","handlingStrategy":"fallback","validationCode":"// probe readability first\ntry { await file.slice(0, 8).text(); } catch { showPasteFallback(); return; }","typeGuard":"const isReadableFile = (f: Pick<File, \"text\">): f is File & { text(): Promise<string> } => typeof f.text === \"function\";","tryCatchPattern":"try {\n  const key = await readGitHubPrivateKeyFile(file);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"couldn't read\")) {\n    openPasteKeyTextarea();\n  } else { throw err; }\n}","preventionTips":["Never delete or move a picked file before submission completes","Always offer the paste-key textarea as an alternative input","Catch DOMException from file.text() and route to the paste path","Verify the file opens in a local text editor as plain text"],"tags":["file-read","browser","github-app","fallback"],"backgroundTag":"file-read-failed","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}