{"record":{"id":"cb451d94682b3171","repo":"firecrawl/open-lovable","slug":"morph-api-key-is-not-set","errorCode":null,"errorMessage":"MORPH_API_KEY is not set","messagePattern":"MORPH_API_KEY is not set","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/morph-fast-apply.ts","lineNumber":43,"sourceCode":"    'package-lock.json',\n    'tsconfig.json',\n    'postcss.config.js'\n  ]);\n\n  const fileName = normalizedPath.split('/').pop() || '';\n  if (!normalizedPath.startsWith('src/') &&\n      !normalizedPath.startsWith('public/') &&\n      normalizedPath !== 'index.html' &&\n      !configFiles.has(fileName)) {\n    normalizedPath = 'src/' + normalizedPath;\n  }\n\n  const fullPath = `/home/user/app/${normalizedPath}`;\n  return { normalizedPath, fullPath };\n}\n\nasync function morphChatCompletionsCreate(payload: any) {\n  if (!process.env.MORPH_API_KEY) throw new Error('MORPH_API_KEY is not set');\n  const res = await fetch('https://api.morphllm.com/v1/chat/completions', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n      'Authorization': `Bearer ${process.env.MORPH_API_KEY}`\n    },\n    body: JSON.stringify(payload)\n  });\n  if (!res.ok) {\n    const text = await res.text();\n    throw new Error(`Morph API error ${res.status}: ${text}`);\n  }\n  return res.json();\n}\n\n// Parse <edit> blocks from LLM output\nexport function parseMorphEdits(text: string): MorphEditBlock[] {\n  const edits: MorphEditBlock[] = [];","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/firecrawl/open-lovable/blob/69bd93bae7a9c97ef989eb70aabe6797fb3dac89/lib/morph-fast-apply.ts#L25-L61","documentation":"This error is thrown at the top of morphChatCompletionsCreate in lib/morph-fast-apply.ts:43 as a fail-fast guard: the module talks directly to Morph's OpenAI-compatible endpoint (https://api.morphllm.com/v1/chat/completions) and refuses to make the network call when process.env.MORPH_API_KEY is falsy. It is a deliberate configuration check, not a network failure — the request is never sent, so the caller always gets a local, deterministic error instead of a confusing 401 from Morph.","triggerScenarios":"Any apply/edit flow that reaches morphChatCompletionsCreate (called from the resp path of morph-fast-apply.ts) while MORPH_API_KEY is absent from the runtime environment: local dev without .env, deployment (Vercel/Docker) where the secret was never added, a typo like MORPH_MORPH_API_KEY or MOPRH_API_KEY, or code running in a context (edge runtime, test) that does not load the .env file.","commonSituations":"Fresh clone where .env.example wasn't copied to .env; adding the key locally but forgetting to add it to production env vars; CI/test environment lacking the secret; serverless deploy where env vars weren't redeployed after being set; wrong variable name casing.","solutions":["Set MORPH_API_KEY in your .env file locally: echo 'MORPH_API_KEY=morph-...' >> .env, then restart the dev server (Next.js does not hot-reload new env vars).","Add MORPH_API_KEY to the production/hosting environment secrets (Vercel project settings, Docker env, CI secrets) and redeploy so the running process picks it up.","Verify the variable name is exactly MORPH_API_KEY (case-sensitive) and that you have a valid key from morphllm.com.","Add a startup validation or a clear user-facing response mapping so this error tells the operator to configure the key rather than surfacing a raw 500.","Optionally lazy-check at module load (or a config module) so misconfiguration is caught at boot instead of mid-request."],"exampleFix":"// before\nasync function morphChatCompletionsCreate(payload: any) {\n  if (!process.env.MORPH_API_KEY) throw new Error('MORPH_API_KEY is not set');\n  const res = await fetch('https://api.morphllm.com/v1/chat/completions', {\n// after\nasync function morphChatCompletionsCreate(payload: any) {\n  if (!process.env.MORPH_API_KEY) {\n    throw new Error('MORPH_API_KEY is not set. Add it to .env or your hosting env secrets and restart.');\n  }\n  const res = await fetch('https://api.morphllm.com/v1/chat/completions', {\n","handlingStrategy":"validation","validationCode":"function requireMorphApiKey(): string {\n  const key = process.env.MORPH_API_KEY;\n  if (!key) throw new Error('MORPH_API_KEY is not set — add it to .env or your host env secrets and restart');\n  return key;\n}\n// call before any Morph operation\nconst apiKey = requireMorphApiKey();","typeGuard":"function hasMorphApiKey(env: NodeJS.ProcessEnv = process.env): env is NodeJS.ProcessEnv & { MORPH_API_KEY: string } {\n  return typeof env.MORPH_API_KEY === 'string' && env.MORPH_API_KEY.length > 0;\n}","tryCatchPattern":"try {\n  const result = await applyWithMorph(editBlock);\n} catch (e) {\n  if ((e as Error).message.includes('MORPH_API_KEY is not set')) {\n    return { success: false, error: 'Morph is not configured: set MORPH_API_KEY in your environment' };\n  }\n  throw e;\n}","preventionTips":["Add MORPH_API_KEY to .env locally (copy from .env.example) and to hosting secrets for every environment (preview, production, CI).","Restart the dev server after changing .env — Next.js does not reload env changes on the fly.","Check env var spelling/casing exactly: MORPH_API_KEY.","Validate required env vars at application startup so misconfiguration surfaces at boot, not mid-request.","Rotate keys safely and verify the new key works with a curl against https://api.morphllm.com/v1/chat/completions before deploying."],"tags":["configuration","env-var","morph","missing-api-key"],"backgroundTag":"missing-env-var","analyzedSha":"69bd93bae7a9c97ef989eb70aabe6797fb3dac89","analyzedAt":"2026-08-28T22:20:32.339Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}