{"record":{"id":"5023bcd9b9c93b67","repo":"langgenius/dify","slug":"not-logged-in","errorCode":"not_logged_in","errorMessage":"account has no email; cannot store credential","messagePattern":"account has no email; cannot store credential","errorType":"error_code","errorClass":"BaseError","httpStatus":null,"severity":"error","filePath":"cli/src/commands/auth/login/login.ts","lineNumber":197,"sourceCode":"      w.write(\n        `${cs.successIcon()} Logged in to ${display} as ${cs.bold(s.subject_email)} (external SSO)\\n`,\n      )\n    return\n  }\n  w.write(`${cs.successIcon()} Logged in to ${display}\\n`)\n}\n\nfunction findDefaultWorkspace(\n  s: PollSuccess,\n): { id: string; name: string; role: string } | undefined {\n  if (s.default_workspace_id === undefined || s.default_workspace_id === '') return undefined\n  return s.workspaces?.find((w) => w.id === s.default_workspace_id)\n}\n\nfunction accountEmail(s: PollSuccess): string {\n  const email = (s.account?.email ?? '') !== '' ? s.account!.email : (s.subject_email ?? '')\n  if (email === '') {\n    throw new BaseError({\n      code: ErrorCode.NotLoggedIn,\n      message: 'account has no email; cannot store credential',\n      hint: 'this Dify instance returned no email for the signed-in subject',\n    })\n  }\n  return email\n}\n\nfunction contextFromSuccess(s: PollSuccess): AccountContext {\n  const ctx: AccountContext = {\n    account: s.account\n      ? { id: s.account.id, email: s.account.email, name: s.account.name }\n      : { id: '', email: '', name: '' },\n    token_id: s.token_id,\n  }\n  if (\n    s.subject_email !== undefined &&\n    s.subject_email !== '' &&","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/cli/src/commands/auth/login/login.ts#L179-L215","documentation":"Raised by CustomizedPipelineTemplateApi.post (POST /rag/pipeline/customized/templates/{template_id}) when the SELECT on PipelineCustomizedTemplate by id returns no row. This endpoint returns the stored yaml_content for a customized template. Note this raises a bare ValueError — not werkzeug NotFound — so Flask surfaces it as HTTP 500 rather than 404; this is arguably a bug in status-code mapping. The session is opened in a with block and the check runs inside it.","triggerScenarios":"POST /console/api/rag/pipeline/customized/templates/{template_id} where template_id was never created, was deleted via the DELETE sibling endpoint, or was created by a different tenant (the query has no tenant filter at this line, but the row genuinely must exist).","commonSituations":"Template was deleted between the UI listing it and the user clicking to load its yaml; a stale template_id cached in the UI; cross-instance inconsistency where the row exists on the writer but not yet on the reader.","solutions":["Refresh the customized template list and use a current template_id.","If the template was deleted, recreate it or choose another.","Handle the 500 (ValueError) response defensively in the client and reload the list — and file/fix the controller to raise NotFound for a proper 404."],"exampleFix":"# before\nif not template:\n    raise ValueError(\"Customized pipeline template not found.\")\n# after — return a proper 404\nfrom werkzeug.exceptions import NotFound\nif not template:\n    raise NotFound(\"Customized pipeline template not found.\")","handlingStrategy":"validation","validationCode":"async function customizedTemplateExists(client, templateId: string): Promise<boolean> {\n  const r = await client.get(`/console/api/rag/pipeline/templates?type=customized`);\n  const list = await r.json();\n  return list.pipeline_templates?.some(t => t.id === templateId) ?? false;\n}","typeGuard":"function isKnownCustomizedTemplate(id: string, known: Set<string>): boolean { return known.has(id); }","tryCatchPattern":"try {\n  return await client.post(`/rag/pipeline/customized/templates/${templateId}`);\n} catch (e) {\n  // NOTE: controller raises ValueError -> HTTP 500; treat 500-with-this-message as not-found\n  if (e.response?.status === 500 && /Customized pipeline template not found/i.test(e.response.data?.message || '')) {\n    await refreshCustomizedTemplateList();\n    return null;\n  }\n  throw e;\n}","preventionTips":["List customized templates before referencing an id.","Watch for the status-code mismatch: a missing customized template returns 500 (ValueError), not 404.","Consider patching the controller to raise werkzeug NotFound for a proper 404."],"tags":["rag-pipeline","template","customized","not-found","status-code-bug","rest-api","console"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}