hcengineering/platform · error · PlatformError
No AdapterManager
Error message
No AdapterManager
What it means
LowLevel middleware's static create() requires an AdapterManager on the pipeline context because it builds low-level storage access (find/insert/delete across domain adapters) from it. If context.adapterManager is null/undefined it throws a PlatformError with the unknownStatus 'No AdapterManager'.
Source
Thrown at foundations/server/packages/middleware/src/lowLevel.ts:42
type Ref,
type StorageIterator
} from '@hcengineering/core'
import { PlatformError, unknownStatus } from '@hcengineering/platform'
import type { Middleware, PipelineContext } from '@hcengineering/server-core'
import { BaseMiddleware } from '@hcengineering/server-core'
/**
* Will perform a find inside adapters
* @public
*/
export class LowLevelMiddleware extends BaseMiddleware implements Middleware {
static async create (
ctx: MeasureContext,
context: PipelineContext,
next: Middleware | undefined
): Promise<Middleware | undefined> {
if (context.adapterManager == null) {
throw new PlatformError(unknownStatus('No AdapterManager'))
}
const adapterManager = context.adapterManager
context.lowLevelStorage = {
find (ctx: MeasureContext, domain: Domain): StorageIterator {
return adapterManager.getAdapter(domain, false).find(ctx, domain)
},
load (ctx: MeasureContext, domain: Domain, docs: Ref<Doc>[]): Promise<Doc[]> {
return adapterManager.getAdapter(domain, false).load(ctx, domain, docs)
},
upload (ctx: MeasureContext, domain: Domain, docs: Doc[]): Promise<void> {
return adapterManager.getAdapter(domain, true).upload(ctx, domain, docs)
},
clean (ctx: MeasureContext, domain: Domain, docs: Ref<Doc>[]): Promise<void> {
return adapterManager.getAdapter(domain, true).clean(ctx, domain, docs)
},View on GitHub (pinned to 63e28dc964)
Solutions
- Configure context.adapterManager (add the adapter-manager middleware) before LowLevel.create() in the pipeline
- Check the pipeline factory/order so the AdapterManager middleware runs before LowLevel
- Verify server configuration supplies the storage/adapter settings used to build the AdapterManager
Example fix
// before const pipeline = await Pipeline.create(ctx, context, [LowLevel.create, ...]) // context.adapterManager undefined // after context.adapterManager = new AdapterManager(ctx, storageConfig) const pipeline = await Pipeline.create(ctx, context, [AdapterManager.create, LowLevel.create, ...])
Defensive patterns
Strategy: validation
Validate before calling
if (context.adapterManager == null) {
throw new Error('AdapterManager must be configured before LowLevel.create')
} Type guard
function hasAdapterManager(ctx: PipelineContext): ctx is PipelineContext & { adapterManager: AdapterManager } {
return ctx.adapterManager != null
} Try / catch
try {
await LowLevel.create(ctx, context, next)
} catch (err) {
if (isPlatformErrorWith(err, 'No AdapterManager')) {
throw new Error('pipeline misconfigured: register AdapterManager middleware')
}
throw err
} Prevention
- Always include the AdapterManager middleware before LowLevel in the pipeline
- Validate the full PipelineContext before pipeline creation
- Use the standard pipeline factory instead of hand-rolled middleware lists
- Add a startup assertion that adapterManager exists
When it happens
Trigger: Constructing the pipeline with LowLevel.create() while the PipelineContext was built without an adapterManager (e.g. adapter manager middleware not added or context assembled manually).
Common situations: Missing configuration when assembling the middleware pipeline; forgetting to register the adapterManager middleware before lowLevel; custom pipeline construction that omits context.adapterManager; service bootstrap missing DB adapter configuration.
Related errors
- Low level storage is not available
- Adapter manager should be configured
- Storage adapter should be specified
- Low level storage should be specified
- ReadonlyError
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/769fe9072e215f5c.
Report an issue: GitHub.