{"record":{"id":"49b37e60c1b7642c","repo":"pubkey/rxdb","slug":"qu18","errorCode":"QU18","errorMessage":"RxDB Error-Code: QU18. Hint: Error messages are not included in RxDB core to reduce build size. To show the full error messages and to ensure that you do not make any mistakes when using RxDB, use the dev-mode plugin when you are in development mode: https://rxdb.info/dev-mode.html?console=error","messagePattern":"RxDB Error-Code: QU18\\. Hint: Error messages are not included in RxDB core to reduce build size\\. To show the full error messages and to ensure that you do not make any mistakes when using RxDB, use the dev-mode plugin when you are in development mode: https://rxdb\\.info/dev-mode\\.html\\?console=error","errorType":"error_code","errorClass":"RxError","httpStatus":null,"severity":"error","filePath":"src/rx-query.ts","lineNumber":248,"sourceCode":"     */\n    public _ensureEqualQueue: Promise<boolean> = PROMISE_RESOLVE_FALSE;\n\n    /**\n     * Returns an observable that emits the results\n     * This should behave like an rxjs-BehaviorSubject which means:\n     * - Emit the current result-set on subscribe\n     * - Emit the new result-set when an RxChangeEvent comes in\n     * - Do not emit anything before the first result-set was created (no null)\n     */\n    public _$?: Observable<RxQueryResult>;\n\n    /**\n     * set the new result-data as result-docs of the query\n     * @param newResultData json-docs that were received from the storage\n     */\n    _setResultData(newResultData: RxDocumentData<RxDocType>[] | number | Map<string, RxDocumentData<RxDocType>>): void {\n        if (typeof newResultData === 'undefined') {\n            throw newRxError('QU18', {\n                database: this.collection.database.name,\n                collection: this.collection.name\n            });\n        }\n        if (typeof newResultData === 'number') {\n            this._result = new RxQuerySingleResult<RxDocType>(\n                this as any,\n                [],\n                newResultData\n            );\n            return;\n        } else if (newResultData instanceof Map) {\n            newResultData = Array.from((newResultData as Map<string, RxDocumentData<RxDocType>>).values());\n        }\n\n        const newQueryResult = new RxQuerySingleResult<RxDocType>(\n            this as any,\n            newResultData,","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/pubkey/rxdb/blob/af6fb65f94cd70558d74c23799eda11ff1c15224/src/rx-query.ts#L230-L266","documentation":"QU18 is thrown by RxQuery._setResultData when the storage layer returns undefined as the query result. RxDB expects either an array of documents, a number (for counts), or a Map; undefined means the storage instance returned an invalid result, so RxDB surfaces QU18 naming the database and collection.","triggerScenarios":"A custom RxStorage plugin's query()/count() implementation resolves with undefined (e.g. a missing return statement, an async function returning nothing, or a wrapper that swallows the result).","commonSituations":"Developing or upgrading a custom RxStorage backend; wrapping the storage instance with caching/proxy code that drops return values; version mismatch where a storage plugin returns a shape the core no longer expects.","solutions":["Inspect the RxStorage implementation used by this collection and ensure query()/count() always resolve with RxDocumentData[] , number, or Map, including all early-return paths.","Add a regression test in the storage plugin that every query branch returns a defined value.","Check that the storage plugin version is compatible with the installed RxDB core version and update both together.","Wrap the storage call chain in logging to capture the resolved value before it reaches _setResultData."],"exampleFix":"// before (custom storage)\nasync query(preparedQuery) {\n  if (cached) return cached;\n  // missing return on the slow path\n  this.underlying.query(preparedQuery);\n}\n\n// after\nasync query(preparedQuery) {\n  if (cached) return cached;\n  return this.underlying.query(preparedQuery);\n}","handlingStrategy":"try-catch","validationCode":"const result = await storageInstance.query(preparedQuery);\nif (typeof result === 'undefined') {\n  throw new Error('storage query() returned undefined - fix the RxStorage implementation');\n}","typeGuard":"function isValidStorageResult<T>(r: unknown): r is RxDocumentData<T>[] | number | Map<string, RxDocumentData<T>> {\n  return Array.isArray(r) || typeof r === 'number' || r instanceof Map;\n}","tryCatchPattern":"try {\n  const docs = await query.exec();\n} catch (err) {\n  if (err?.code === 'QU18') {\n    console.error(`storage for ${err.parameters?.database}/${err.parameters?.collection} returned undefined`);\n    throw new Error('invalid RxStorage plugin result');\n  }\n  throw err;\n}","preventionTips":["When writing custom RxStorage plugins, return a value from every branch of query()/count().","Keep storage plugin versions in lockstep with the RxDB core version.","Add automated storage-conformance tests that assert defined results for all query shapes."],"tags":["query","custom-storage","invalid-result"],"backgroundTag":"storage-returned-undefined","analyzedSha":"af6fb65f94cd70558d74c23799eda11ff1c15224","analyzedAt":"2026-08-31T23:32:37.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}