{"record":{"id":"98e9a3d14f82dc0d","repo":"dmtrKovalenko/fff","slug":"fff-picker-factory-is-not-initialized","errorCode":null,"errorMessage":"FFF picker factory is not initialized","messagePattern":"FFF picker factory is not initialized","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/pi-fff/src/index.ts","lineNumber":479,"sourceCode":"  }\n\n  // in case cwd changes we need to figure this out\n  function ensureFinder(cwd: string): Promise<FileFinderApi> {\n    if (mainFinder && !mainFinder.isDestroyed && finderCwd === cwd)\n      return Promise.resolve(mainFinder);\n\n    if (finderPromise) return finderPromise;\n\n    finderPromise = (async () => {\n      if (mainFinder && !mainFinder.isDestroyed) {\n        mainFinder.destroy();\n        mainFinder = null;\n        finderCwd = null;\n      }\n\n      // if the dbs can't be opened the factory falls back to a db-less picker,\n      // e.g. when some other process corrupts the lock\n      if (!pickers) throw new Error(\"FFF picker factory is not initialized\");\n      mainFinder = await pickers.create({\n        basePath: cwd,\n        enableHomeDirScanning,\n        enableFsRootScanning,\n        followSymlinks,\n      });\n      finderCwd = cwd;\n      return mainFinder;\n    })().finally(() => {\n      finderPromise = null;\n    });\n\n    return finderPromise;\n  }\n\n  function stopHomeScanStatus(): void {\n    if (homeScanTimer) {\n      clearInterval(homeScanTimer);","sourceCodeStart":461,"sourceCodeEnd":497,"githubUrl":"https://github.com/dmtrKovalenko/fff/blob/7f8537e70f0ea1210f9acbbfc4640141105cdc78/packages/pi-fff/src/index.ts#L461-L497","documentation":"This error means the FilePickerFactory (`pickers`) is null when `ensureFinder` tries to create the main picker. The factory is created once by `initializeFinderFactories()` and nulled by `destroyFinder()` (e.g. on session end or cwd change teardown). Throwing is a fail-fast guard against using the picker subsystem after teardown or before init instead of silently creating pickers with no database backing.","triggerScenarios":"Calling `ensureFinder` (directly or via the find/grep/multiGrep tools) after `destroyFinder()` has run; or calling tools before the extension's session_start event ran `initializeFinderFactories()`. A stale/corrupted LMDB lock does NOT cause this — the factory falls back to a db-less picker for that.","commonSituations":"Invoking a tool handler from a second session after the first one shut down; racing the extension lifecycle so a tool fires during teardown; embedding the extension programmatically and forgetting to emit session_start before calling tools.","solutions":["Ensure the fff extension's session_start hook runs (it calls initializeFinderFactories) before any find/grep tool is invoked","If you changed cwd or ended a session, re-start the session so factories are re-created instead of reusing stale tool handles","If embedding the extension, call the initialization path explicitly before first tool use","Do not call tool handlers after session shutdown; create a fresh extension instance per session"],"exampleFix":"// before\ngrepTool.execute(id, params) // fired after session teardown\n\n// after\nif (!sessionActive) await startSession(); // re-initializes pickers\nawait grepTool.execute(id, params)","handlingStrategy":"try-catch","validationCode":"if (!fff.isInitialized?.()) await startSession();","typeGuard":"function hasFactory(e: { isReady?: () => boolean }): boolean { return typeof e.isReady === 'function' && e.isReady(); }","tryCatchPattern":"try { await ensureFinder(cwd); } catch (e) { if (String(e).includes('not initialized')) { await startSession(); await ensureFinder(cwd); } else throw e; }","preventionTips":["Always start the session before invoking find/grep tools","Create one extension instance per session and discard handles on teardown","Don't interleave tool calls with session_end events"],"tags":["lifecycle","initialization","null-state"],"backgroundTag":"internal-invariant-violation","analyzedSha":"7f8537e70f0ea1210f9acbbfc4640141105cdc78","analyzedAt":"2026-09-10T07:26:53.407Z","contentChangedAt":"2026-09-10T07:26:53.407Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}