RocketChat/Rocket.Chat · error · Error
failed-to-create-direct-call
Error message
failed-to-create-direct-call
What it means
Thrown by startDirect() after the call document was created, the onNewVideoConference app event fired and maybeCreateDiscussion ran: getUnfiltered(callId) returns null. getUnfiltered bypasses room/user visibility filters, so null means the video_conference record itself is gone - typically a provider app handler deleted or moved it during runNewVideoConferenceEvent, a model hook removed it, or read-after-write inconsistency in the database.
Source
Thrown at apps/meteor/server/services/video-conference/service.ts:759
const callId = await VideoConferenceModel.createDirect({
...extraData,
rid,
createdBy: {
_id: user._id,
name: user.name as string,
username: user.username as string,
},
providerName,
});
await this.runNewVideoConferenceEvent(callId);
await this.maybeCreateDiscussion(callId, user);
const call = (await this.getUnfiltered(callId)) as IDirectVideoConference | null;
if (!call) {
throw new Error('failed-to-create-direct-call');
}
const url = await this.generateNewUrl(call);
await VideoConferenceModel.setUrlById(callId, url);
const messageId = await this.createMessage(call, user);
call.messages.started = messageId;
await VideoConferenceModel.setMessageById(callId, 'started', messageId);
// After 40 seconds if the status is still "calling", we cancel the call automatically.
setTimeout(async () => {
try {
const call = await VideoConferenceModel.findOneById<IDirectVideoConference>(callId);
if (call) {
await this.endDirectCall(call);
if (call.status !== VideoConferenceStatus.CALLING) {
return;
}View on GitHub (pinned to e4b8178b20)
Solutions
- Inspect installed apps' onNewVideoConference handlers for deletion/recreation logic and fix or remove the offending app
- Check the video_conference collection to confirm the doc exists right after create (distinguishes deletion from failed insert)
- If using a replica set, ensure reads for this path hit the primary or tolerate replication lag
- Retry the start call once - transient races resolve on a second attempt
Example fix
// before
const call = await getUnfiltered(callId);
if (!call) throw new Error('failed-to-create-direct-call');
// after
let call = await getUnfiltered(callId);
if (!call) {
await new Promise((r) => setTimeout(r, 100));
call = await getUnfiltered(callId); // tolerate replication lag / handler rewrite
}
if (!call) throw new Error('failed-to-create-direct-call'); Defensive patterns
Strategy: try-catch
Try / catch
try {
await videoConfService.startCall(user, { _id: rid, uids });
} catch (err) {
if (err instanceof Error && err.message === 'failed-to-create-direct-call') {
// log callId context, inspect provider app handlers, then surface a retry to the user
}
} Prevention
- Audit provider apps' onNewVideoConference handlers for deletion or recreation of call docs
- Keep the video_conference write/read path on the primary in replica-set deployments
- Log the created callId immediately so a vanished doc is traceable
When it happens
Trigger: A provider app's new-conference handler removes or recreates the call doc during creation; a DB observer/hook deletes it; in replica-set deployments the read routes to a secondary that has not yet applied the insert.
Common situations: Custom provider apps that 'clean up' calls they do not recognize; app versions whose handlers reject unconfigured providers; local dev against a lagging mongod replica set.
Related errors
- failed-to-create-group-call
- A video conference must exist to update.
- apps-engine-not-initialized
- video-conf-provider-unavailable
- invalid-call-status
AI-assisted analysis of RocketChat/Rocket.Chat@e4b8178b20 (2026-08-18).
Data as JSON: /api/errors/3f109af45df9f27b.
Report an issue: GitHub.