{"record":{"id":"b0ba2aa1a7fd8665","repo":"santifer/career-ops","slug":"no-applications-database-found-under-the-career","errorCode":null,"errorMessage":"No \"Applications\" database found under the Career Ops page — create it and share the integration with it.","messagePattern":"No \"Applications\" database found under the Career Ops page — create it and share the integration with it\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"plugins/notion/index.mjs","lineNumber":37,"sourceCode":"// internal integration. Enable in config/plugins.yml; keys in .env.\n//\n//   node plugins.mjs run notion export            # mirror tracker → Notion\n//   node plugins.mjs run notion search \"platform\" # read matching records → pipeline\n\nimport { createNotionClient, rich, canonicalStatus } from './_notion.mjs';\n\nfunction clientFromCtx(ctx) {\n  return createNotionClient({\n    token: ctx?.env?.NOTION_ACCESS_TOKEN,\n    parent: ctx?.env?.NOTION_PARENT_PAGE_ID,\n    fetch: ctx?.fetch, // route through the engine's allowedHosts/redirect guard\n  });\n}\n\nasync function applicationsDb(client) {\n  const dbs = await client.resolveDBs();\n  const apps = dbs['Applications'];\n  if (!apps) throw new Error('No \"Applications\" database found under the Career Ops page — create it and share the integration with it.');\n  return apps;\n}\n\n/**\n * Parse a tracker score cell into a numeric value for the Notion DB Score property.\n *\n * Scores in applications.md may be formatted like `4.2/5`, `**4.2/5**`, `4.25`, etc.\n * Strips formatting and extracts the first numeric value so slash-formatted\n * scores (e.g. 4.2/5) are not mangled into 4.25 (#1414).\n *\n * @param {unknown} s - Raw score value from tracker row.\n * @returns {number} Parsed score, or NaN if no valid number is present.\n */\nexport function parseScore(s) {\n  const m = String(s ?? '').replace(/\\*\\*/g, '').match(/([\\d.]+)/);\n  return m ? parseFloat(m[1]) : NaN;\n}\n","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/plugins/notion/index.mjs#L19-L55","documentation":"After resolving all child databases under the parent page, the notion plugin looks specifically for one named 'Applications'. If none is found (dbs['Applications'] is undefined), it throws with instructions to create it and share it with the integration. This is a setup-completeness guard, not a runtime failure.","triggerScenarios":"Running any notion plugin operation that targets the Applications DB (e.g. syncing the tracker) when the parent page exists and is reachable, but contains no child database titled exactly 'Applications'. A database with a different title (e.g. 'applications' lowercase, 'Job Applications') will NOT match — the lookup is by exact title string.","commonSituations":"User set up the token and parent page id but hasn't created the Applications database yet; the database exists but has a slightly different name; the database exists with the right name but was created as a regular page (not a database / 'data source'); the parent page is shared with the integration but the child database isn't (then resolveDBs can't see it, though that more often yields a missing entry than an error).","solutions":["In Notion, under the 'Career Ops' parent page, create a new database in-line named exactly 'Applications' (capital A, plural).","Ensure the database is shared with the integration: open the database → ⋯ → Connect to → your integration. (Sharing the parent page alone may not propagate to children.)","Re-run the notion plugin. If it still fails, verify resolveDBs sees the DB name — the integration must have access to the child database specifically."],"exampleFix":"// Not a code fix — Notion setup:\n// 1. Career Ops page → Add a page → Database (full page) → title: \"Applications\"\n// 2. Applications DB → ⋯ menu → Connect to → <integration name>\n// 3. node plugins.mjs run notion","handlingStrategy":"validation","validationCode":"// Pre-flight: ensure the Applications DB exists and is shared.\nasync function ensureApplicationsDb(client) {\n  const dbs = await client.resolveDBs();\n  if (!dbs['Applications']) {\n    throw new Error('Setup incomplete: create an \"Applications\" database under the Career Ops page and share it with the integration.');\n  }\n  return dbs['Applications'];\n}","typeGuard":"/** @param {unknown} dbs @returns {dbs is Record<string, string>} */\nfunction isDbMap(dbs) {\n  return !!dbs && typeof dbs === 'object' && 'Applications' in dbs;\n}","tryCatchPattern":"try {\n  const appId = await applicationsDb(client);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('Applications\" database')) {\n    console.error('Notion setup step missing: create + share the Applications DB.');\n  } else throw err;\n}","preventionTips":["Title databases exactly as the code looks them up (case-sensitive) — 'Applications', not 'applications'.","After creating a child DB, explicitly connect it to the integration; parent-level sharing does not always inherit.","Add a setup self-check (resolveDBs + assert key DBs present) to the plugin's doctor step."],"tags":["notion","config","setup","plugin"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}