{"record":{"id":"fe9b98a8b034ef98","repo":"hcengineering/platform","slug":"storage-adapter-should-be-specified","errorCode":null,"errorMessage":"Storage adapter should be specified","messagePattern":"Storage adapter should be specified","errorType":"error_code","errorClass":"PlatformError","httpStatus":null,"severity":"error","filePath":"foundations/server/packages/middleware/src/triggers.ts","lineNumber":89,"sourceCode":"      },\n      30 * 60 * 1000\n    )\n  }\n\n  async close (): Promise<void> {\n    clearInterval(this.intervalId)\n  }\n\n  static async create (ctx: MeasureContext, context: PipelineContext, next?: Middleware): Promise<Middleware> {\n    // we need to init triggers from model first.\n    const triggers = new TriggersMiddleware(context, next)\n    await triggers.init(ctx)\n    return triggers\n  }\n\n  async init (ctx: MeasureContext): Promise<void> {\n    if (this.context.storageAdapter == null) {\n      throw new PlatformError(unknownError('Storage adapter should be specified'))\n    }\n    if (this.context.lowLevelStorage == null) {\n      throw new PlatformError(unknownError('Low level storage should be specified'))\n    }\n    this.storageAdapter = this.context.storageAdapter\n    this.triggers.init(this.context.modelDb)\n  }\n\n  async tx (ctx: MeasureContext<SessionData>, tx: Tx[]): Promise<TxMiddlewareResult> {\n    await this.triggers.tx(tx)\n    const result = await this.provideTx(ctx, tx)\n\n    const ftx = filterBroadcastOnly(tx, this.context.hierarchy)\n    if (ftx.length > 0) {\n      await this.processDerived(ctx, ftx)\n    }\n    return result\n  }","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/server/packages/middleware/src/triggers.ts#L71-L107","documentation":"Triggers middleware's init() needs a storage adapter on the pipeline context to perform storage operations (e.g. removing docs on model changes). If context.storageAdapter is null it throws unknownError('Storage adapter should be specified').","triggerScenarios":"Calling init() (or create() which calls init) on a Triggers middleware instance while PipelineContext.storageAdapter was never set.","commonSituations":"Pipeline assembled without registering the storage adapter; misconfigured database connection so the adapter was not created; tests constructing the context without a storage adapter.","solutions":["Set context.storageAdapter (via the storage middleware or manual assignment) before Triggers.init/create","Verify the storage/DB configuration so the storage adapter middleware initializes successfully","Check middleware ordering so the storage adapter exists before triggers initialization"],"exampleFix":"// before\nconst triggers = await Triggers.create(ctx, context, ...) // context.storageAdapter == null\n// after\ncontext.storageAdapter = await getStorageAdapter(ctx, dbConfig)\nconst triggers = await Triggers.create(ctx, context, ...)","handlingStrategy":"validation","validationCode":"if (context.storageAdapter == null) {\n  throw new Error('storageAdapter must be configured before Triggers.init')\n}","typeGuard":"function hasStorageAdapter(ctx: PipelineContext): ctx is PipelineContext & { storageAdapter: StorageAdapter } {\n  return ctx.storageAdapter != null\n}","tryCatchPattern":"try {\n  await triggers.init(ctx)\n} catch (err) {\n  if (isPlatformErrorWith(err, 'Storage adapter should be specified')) {\n    throw new Error('register storage middleware before triggers')\n  }\n  throw err\n}","preventionTips":["Register the storage middleware before Triggers in the pipeline","Validate PipelineContext completeness at startup","Keep DB connection config checked before pipeline build","Add pipeline-assembly unit tests"],"tags":["configuration","storage","triggers"],"backgroundTag":"missing-pipeline-dependency","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}