hcengineering/platform · error · PlatformError

Storage adapter should be specified

Error message

Storage adapter should be specified

What it means

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').

Source

Thrown at foundations/server/packages/middleware/src/triggers.ts:89

      },
      30 * 60 * 1000
    )
  }

  async close (): Promise<void> {
    clearInterval(this.intervalId)
  }

  static async create (ctx: MeasureContext, context: PipelineContext, next?: Middleware): Promise<Middleware> {
    // we need to init triggers from model first.
    const triggers = new TriggersMiddleware(context, next)
    await triggers.init(ctx)
    return triggers
  }

  async init (ctx: MeasureContext): Promise<void> {
    if (this.context.storageAdapter == null) {
      throw new PlatformError(unknownError('Storage adapter should be specified'))
    }
    if (this.context.lowLevelStorage == null) {
      throw new PlatformError(unknownError('Low level storage should be specified'))
    }
    this.storageAdapter = this.context.storageAdapter
    this.triggers.init(this.context.modelDb)
  }

  async tx (ctx: MeasureContext<SessionData>, tx: Tx[]): Promise<TxMiddlewareResult> {
    await this.triggers.tx(tx)
    const result = await this.provideTx(ctx, tx)

    const ftx = filterBroadcastOnly(tx, this.context.hierarchy)
    if (ftx.length > 0) {
      await this.processDerived(ctx, ftx)
    }
    return result
  }

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Set context.storageAdapter (via the storage middleware or manual assignment) before Triggers.init/create
  2. Verify the storage/DB configuration so the storage adapter middleware initializes successfully
  3. Check middleware ordering so the storage adapter exists before triggers initialization

Example fix

// before
const triggers = await Triggers.create(ctx, context, ...) // context.storageAdapter == null
// after
context.storageAdapter = await getStorageAdapter(ctx, dbConfig)
const triggers = await Triggers.create(ctx, context, ...)
Defensive patterns

Strategy: validation

Validate before calling

if (context.storageAdapter == null) {
  throw new Error('storageAdapter must be configured before Triggers.init')
}

Type guard

function hasStorageAdapter(ctx: PipelineContext): ctx is PipelineContext & { storageAdapter: StorageAdapter } {
  return ctx.storageAdapter != null
}

Try / catch

try {
  await triggers.init(ctx)
} catch (err) {
  if (isPlatformErrorWith(err, 'Storage adapter should be specified')) {
    throw new Error('register storage middleware before triggers')
  }
  throw err
}

Prevention

When it happens

Trigger: Calling init() (or create() which calls init) on a Triggers middleware instance while PipelineContext.storageAdapter was never set.

Common situations: Pipeline assembled without registering the storage adapter; misconfigured database connection so the adapter was not created; tests constructing the context without a storage adapter.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/fe9b98a8b034ef98. Report an issue: GitHub.