pubkey/rxdb · error · RxError
VD2
VD2
Error message
RxDB Error-Code: ${message}.
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
Find out more about this error here: https://rxdb.info/errors.html?console=errors#VD2
Still stuck? Ask in the RxDB Discord: https://rxdb.info/chat
What it means
VD2 (VD = validation) is thrown by throwIfIsStorageWriteError in src/rx-storage-helper.ts:174 when an underlying RxStorage write operation rejects a document with HTTP-style status 422, meaning the document failed the RxJSONSchema validation. RxDB validates every write against the collection schema at the storage layer; instead of writing invalid data it surfaces this error. The 409 case is routed to the CONFLICT error, everything else passes through, so VD2 specifically means 'the document shape violates the schema'.
Source
Thrown at src/rx-storage-helper.ts:174
);
}
export function throwIfIsStorageWriteError<RxDocType>(
collection: RxCollection<RxDocType, any, any>,
documentId: string,
writeData: RxDocumentWriteData<RxDocType> | RxDocType,
error: RxStorageWriteError<RxDocType> | undefined
) {
if (error) {
if (error.status === 409) {
throw newRxError('CONFLICT', {
collection: collection.name,
id: documentId,
writeError: error,
data: writeData
});
} else if (error.status === 422) {
throw newRxError('VD2', {
collection: collection.name,
id: documentId,
writeError: error,
data: writeData
});
} else {
throw error;
}
}
}
/**
* Use a counter-based event bulk ID instead of randomToken()
* for better performance. The prefix ensures uniqueness across instances.
*/
const EVENT_BULK_ID_PREFIX = randomToken(10);
let eventBulkCounter = 0;View on GitHub (pinned to af6fb65f94)
Solutions
- Log err.parameters.writeError and err.parameters.data (the RxError carries them) to see exactly which schema keyword failed and for which document id.
- Temporarily add the dev-mode plugin in development to get the full human-readable error message instead of the error code.
- Fix the document so it matches the collection schema (required fields, types, primary key maxLength), then retry the write.
- If writing partial data, fetch the existing document first and merge, or use incrementalUpsert()/modify() instead of upsert().
- If the schema itself is wrong for your data (e.g. maxLength: 100 is too small for your ids), bump the schema (new collection/version + migration) rather than writing invalid data.
Example fix
// before: partial doc fails 422 validation
await collection.upsert({ id: 'foo', name: 'x' }); // VD2: missing required 'age'
// after: full valid document matching the schema
await collection.upsert({ id: 'foo', name: 'x', age: 42 }); Defensive patterns
Strategy: validation
Validate before calling
// validate a candidate document against the collection schema before writing
function validateAgainstSchema(doc, rxSchema) {
const errors = rxSchema.validate(doc); // returns list of schema errors
if (errors.length > 0) {
throw new Error('Invalid document: ' + JSON.stringify(errors));
}
}
// simpler checks before insert/upsert
const pk = collection.schema.primaryPath;
if (typeof doc[pk] !== 'string' || doc[pk].length > collection.schema.getSchemaOfMainPath()[pk].maxLength) {
throw new Error('Primary key missing or exceeds maxLength');
} Try / catch
try {
await collection.insert(doc);
} catch (err) {
if (err && err.code === 'VD2') {
console.error('Schema validation failed for id', err.parameters.id);
console.error(JSON.stringify(err.parameters.writeError, null, 2));
console.error('Data was:', JSON.stringify(err.parameters.data, null, 2));
return; // handle invalid data explicitly
}
throw err;
} Prevention
- Run with the dev-mode plugin in development so validation errors show full messages immediately.
- Keep a single factory function that constructs documents so every write goes through the same shape check.
- Always write complete documents via insert()/upsert(); use incrementalUpsert() or modify() for partial updates.
- Size the primary key maxLength generously and validate user-supplied ids before inserting.
- Add unit tests that insert representative documents through the real collection before shipping.
When it happens
Trigger: Calling insert(), upsert(), _saveData() (used by incrementalModify/save), or remove() on an RxCollection where the written document violates the collection's RxJsonSchema: missing required fields, wrong types, additionalProperties: true violations, maxLength exceeded on the primary key, or invalid attachment metadata. throwIfIsStorageWriteError is also called by replication and migration code paths when they pipe writes through the collection.
Common situations: Writing documents whose primary key (string type) exceeds its declared maxLength; forgetting required fields when constructing documents manually; migrating code between schema versions and writing docs in the old shape; receiving JSON from a server or user input that is not normalized before insert; using upsert() with a partial document instead of a full document.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
AI-assisted analysis of pubkey/rxdb@af6fb65f94 (2026-08-31).
Data as JSON: /api/errors/6d33ebeb0c961d39.
Report an issue: GitHub.