RocketChat/Rocket.Chat · error · Error
A video conference must exist to update.
Error message
A video conference must exist to update.
What it means
Thrown by the video conferences bridge update method when no existing video conference matches the provided call._id (or when _id is absent so the lookup is skipped). Update is a mutation on an existing record; the bridge loads the prior state via VideoConf.getUnfiltered and refuses to proceed if there is nothing to mutate.
Source
Thrown at apps/meteor/app/apps/server/bridges/videoConferences.ts:39
}
protected async create(call: AppVideoConference, appId: string): Promise<string> {
this.orch.debugLog(`The App ${appId} is creating a video conference.`);
return (
await VideoConf.create({
type: 'videoconference',
...call,
})
).callId;
}
protected async update(call: VideoConference, appId: string): Promise<void> {
this.orch.debugLog(`The App ${appId} is updating a video conference.`);
const oldData = call._id && (await VideoConf.getUnfiltered(call._id));
if (!oldData) {
throw new Error('A video conference must exist to update.');
}
const data = (this.orch.getConverters()?.get('videoConferences') as AppVideoConferencesConverter).convertAppVideoConference(call);
await VideoConf.setProviderData(call._id, data.providerData);
for (const { _id, ts } of data.users) {
if (oldData.users.find((user) => user._id === _id)) {
continue;
}
await VideoConf.addUser(call._id, _id, ts);
}
if (data.endedBy && data.endedBy._id !== oldData.endedBy?._id) {
await VideoConf.setEndedBy(call._id, data.endedBy._id);
} else if (data.endedAt) {
await VideoConf.setEndedAt(call._id, data.endedAt);
}View on GitHub (pinned to f9d3ec372b)
Solutions
- Ensure the video conference was created (create returned a callId) before calling update.
- Pass the exact callId returned by create as call._id.
- Re-fetch the conference before updating to confirm it still exists.
Example fix
// before
await videoConf.update({ ...staleCall, status: 'ended' });
// after
const existing = await VideoConf.getUnfiltered(callId);
if (!existing) {
// conference already gone; nothing to update
return;
}
await videoConf.update({ ...existing, status: 'ended' }); Defensive patterns
Strategy: validation
Validate before calling
if (!call._id) {
throw new Error('Cannot update video conference: missing _id');
}
const existing = await VideoConf.getUnfiltered(call._id);
if (!existing) {
throw new Error('Cannot update video conference: not found');
} Type guard
function hasExistingCallId(call: VideoConference): call is VideoConference & { _id: string } {
return typeof call._id === 'string' && call._id.length > 0;
} Try / catch
try {
await videoConf.update(call);
} catch (err) {
if (err instanceof Error && err.message === 'A video conference must exist to update.') {
// conference was deleted; create a new one instead
} else {
throw err;
}
} Prevention
- Always pass the callId returned by create as call._id.
- Re-fetch the conference before updating to confirm it still exists.
- Handle create-then-update races by re-creating if missing.
When it happens
Trigger: App calls update with a call object whose _id is undefined, refers to a conference that was never created, or to one that has been deleted. The check is `const oldData = call._id && (await VideoConf.getUnfiltered(call._id)); if (!oldData) throw ...`.
Common situations: App updates a conference from a stale/cached object whose id no longer exists; conference ended and was cleaned up before the update; _id field stripped during serialization; race between create and update.
Related errors
- Room id not found
- 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.
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/a40a519ebebef4f2.
Report an issue: GitHub.