RocketChat/Rocket.Chat · error · Error
Attempted to store an invalid data type, it must be an objec
Error message
Attempted to store an invalid data type, it must be an object.
What it means
Thrown by AppPersistenceBridge.create when the data argument fails `typeof data !== 'object'`. The persistence layer stores arbitrary app data as a Mongo document; non-object payloads (string, number, boolean, undefined) cannot be persisted as a sub-document and are rejected. Note the guard uses typeof, so null passes (typeof null === 'object') and arrays also pass — both will be stored as-is, which may not be intended.
Source
Thrown at apps/meteor/app/apps/server/bridges/persistence.ts:21
import type { RocketChatAssociationRecord } from '@rocket.chat/apps-engine/definition/metadata';
import type { InsertOneResult } from 'mongodb';
export class AppPersistenceBridge extends PersistenceBridge {
constructor(private readonly orch: IAppServerOrchestrator) {
super();
}
protected async purge(appId: string): Promise<void> {
this.orch.debugLog(`The App's persistent storage is being purged: ${appId}`);
await this.orch.getPersistenceModel().remove({ appId });
}
protected async create(data: object, appId: string): Promise<string> {
this.orch.debugLog(`The App ${appId} is storing a new object in their persistence.`);
if (typeof data !== 'object') {
throw new Error('Attempted to store an invalid data type, it must be an object.');
}
return this.orch
.getPersistenceModel()
.insertOne({ appId, data })
.then(({ insertedId }: InsertOneResult) => (insertedId as unknown as string) || '');
}
protected async createWithAssociations(data: object, associations: Array<RocketChatAssociationRecord>, appId: string): Promise<string> {
this.orch.debugLog({
msg: `The App ${appId} is storing a new object in their persistence that is associated with some models.`,
associations,
});
if (typeof data !== 'object') {
throw new Error('Attempted to store an invalid data type, it must be an object.');
}
View on GitHub (pinned to f9d3ec372b)
Solutions
- Pass a plain object: wrap scalars, e.g. `{ value: count }` instead of the bare number.
- If receiving serialized data, parse it first: `const data = JSON.parse(raw); if (typeof data !== 'object') ...`.
- Avoid null and arrays if you expect a record shape — add your own Array.isArray / null check before calling.
Example fix
// before await persistence.create(JSON.stringify(payload), appId); // after await persistence.create(payload, appId);
Defensive patterns
Strategy: type-guard
Validate before calling
if (data === null || data === undefined || typeof data !== 'object' || Array.isArray(data)) {
throw new Error('persistence.create requires a plain object');
}
await persistence.create(data, appId); Type guard
function isPlainObject(value: unknown): value is Record<string, unknown> {
return typeof value === 'object' && value !== null && !Array.isArray(value);
} Prevention
- Never pass a serialized JSON string — pass the parsed object.
- Wrap scalars in a record ({ value: n }) before persisting.
- Add an isPlainObject guard at your App's persistence wrapper so the bridge never sees a bad payload.
When it happens
Trigger: An App calls persistence.create(data) (via the persistence accessor) passing a primitive: a JSON string instead of a parsed object, a number counter, a boolean flag, or undefined because the variable was never assigned.
Common situations: Forgetting to JSON.parse a serialized payload before persisting; storing a scalar where an object was expected; refactoring that changed a value from object to primitive without updating the persistence call.
Related errors
- Invalid Api parameter provided, it must be a valid IApi obje
- Invalid command parameter provided, must be a string.
- Invalid Slash Command parameter provided, it must be a valid
- The environmental variable "${envVarName}" is not readable.
- auth option should be of the form "username:password"
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/0c37e548ca89e698.
Report an issue: GitHub.