{"record":{"id":"19ff4bfe703d9745","repo":"tinyhumansai/openhuman","slug":"asc-key-id-asc-issuer-id-and-asc-key-path-are-re","errorCode":null,"errorMessage":"ASC_KEY_ID, ASC_ISSUER_ID, and ASC_KEY_PATH are required.","messagePattern":"ASC_KEY_ID, ASC_ISSUER_ID, and ASC_KEY_PATH are required\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/ios-appstore-metadata.mjs","lineNumber":28,"sourceCode":"const screenshotDir = path.join(rootDir, \"fastlane/screenshots/en-US\");\nconst apiBase = \"https://api.appstoreconnect.apple.com/v1\";\n\nconst appId = process.env.ASC_APP_ID || \"6761229174\";\nconst locale = process.env.ASC_LOCALE || \"en-US\";\nconst platform = process.env.ASC_PLATFORM || \"IOS\";\nconst screenshotDisplayType =\n  process.env.ASC_SCREENSHOT_DISPLAY_TYPE || \"APP_IPHONE_67\";\nconst versionString =\n  process.env.ASC_VERSION_STRING ||\n  JSON.parse(await readFile(path.join(rootDir, \"app/package.json\"), \"utf8\"))\n    .version;\n\nconst keyId = process.env.ASC_KEY_ID;\nconst issuerId = process.env.ASC_ISSUER_ID;\nconst keyPath = process.env.ASC_KEY_PATH;\n\nif (!keyId || !issuerId || !keyPath) {\n  throw new Error(\"ASC_KEY_ID, ASC_ISSUER_ID, and ASC_KEY_PATH are required.\");\n}\n\nfunction base64Url(input) {\n  return Buffer.from(input)\n    .toString(\"base64\")\n    .replaceAll(\"+\", \"-\")\n    .replaceAll(\"/\", \"_\")\n    .replaceAll(\"=\", \"\");\n}\n\nasync function createJwt() {\n  const privateKey = await readFile(keyPath, \"utf8\");\n  const now = Math.floor(Date.now() / 1000);\n  const header = { alg: \"ES256\", kid: keyId, typ: \"JWT\" };\n  const payload = {\n    iss: issuerId,\n    aud: \"appstoreconnect-v1\",\n    iat: now,","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/ios-appstore-metadata.mjs#L10-L46","documentation":"scripts/ios-appstore-metadata.mjs is a top-level-await ESM script that talks to the App Store Connect API; it fails fast at startup unless all three credentials are present: ASC_KEY_ID (the API key id), ASC_ISSUER_ID (the team's issuer id), and ASC_KEY_PATH (path to the .p8 private key file). Other knobs have defaults (ASC_APP_ID defaults to 6761229174, ASC_LOCALE to en-US), but the key material never does.","triggerScenarios":"Running `node scripts/ios-appstore-metadata.mjs` locally without exporting the three env vars; a CI job where the ASC secrets were not mapped into the step's env; ASC_KEY_PATH set but ASC_KEY_ID/ASC_ISSUER_ID forgotten (all three are checked together, the error fires on the first missing one).","commonSituations":"Fresh machine without the release .env; rotating a revoked ASC key and forgetting to update one of the three values; secrets stored in the CI vault but not referenced in the workflow step.","solutions":["Create an App Store Connect API key (appstoreconnect.apple.com → Users and Access → Integrations → App Manager role or higher) and download the .p8","Export the triple before running: `ASC_KEY_ID=ABCDE12345 ASC_ISSUER_ID=xxxxxxxx-xxxx-... ASC_KEY_PATH=/path/AuthKey_ABCDE12345.p8 node scripts/ios-appstore-metadata.mjs`","In CI, store key id / issuer id / key file as secrets and map all three into the step env (the key file itself can be written from a base64 secret)"],"exampleFix":"# before\nnode scripts/ios-appstore-metadata.mjs\n# → Error: ASC_KEY_ID, ASC_ISSUER_ID, and ASC_KEY_PATH are required.\n\n# after\nexport ASC_KEY_ID=\"ABCDE12345\"\nexport ASC_ISSUER_ID=\"69a6de7f-...-847e5f5c4aa\"\nexport ASC_KEY_PATH=\"$HOME/Downloads/AuthKey_ABCDE12345.p8\"\nnode scripts/ios-appstore-metadata.mjs","handlingStrategy":"validation","validationCode":"const required = ['ASC_KEY_ID', 'ASC_ISSUER_ID', 'ASC_KEY_PATH'];\nconst missing = required.filter(k => !process.env[k]);\nif (missing.length) {\n  console.error(`Missing App Store Connect env: ${missing.join(', ')}`);\n  process.exit(1);\n}\n// then: node scripts/ios-appstore-metadata.mjs","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Wrap the release run in a tiny preflight script that checks the three ASC_* variables and the .p8 file's existence before starting the long upload run","Keep the triple together in CI secrets and map all three in one step env block — partial exports always fail","After rotating an ASC key, update key id, issuer (if team changed) and key path in the same change; the script fails fast so nothing half-applies"],"tags":["app-store-connect","release","env","ci","credentials"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}