mongodb/node-mongodb-native · error · MongoRuntimeError

File not found for id

Error message

File not found for id ${id}

What it means

GridFSBucket.delete (src/gridfs/index.ts:184) throws MongoRuntimeError 'File not found for id' when the deleteOne on the files collection matched zero documents. The driver deletes orphaned chunks first, then reports the missing file. The id type is ObjectId; a mismatched or non-existent id triggers this.

Solutions

  1. Check existence before deleting: const file = await bucket.find({ _id: id }).next(); if (file) await bucket.delete(id).
  2. Make delete idempotent by catching the error and treating 'not found' as success when appropriate.
  3. Verify the id is an ObjectId and that the bucket name/namespace matches where the file was uploaded.

Example fix

// before
await bucket.delete(id); // throws if missing
// after
const file = await bucket.find({ _id: id }).next();
if (file) await bucket.delete(id);
Defensive patterns

Strategy: try-catch

Validate before calling

async function deleteIfExists(bucket, id) {
  const file = await bucket.find({ _id: id }).next();
  if (!file) return false;
  await bucket.delete(id);
  return true;
}

Type guard

function isObjectId(v: unknown): v is ObjectId {
  return v != null && typeof v === 'object' && '_bsontype' in v && (v as any)._bsontype === 'ObjectId';
}

Try / catch

try {
  await bucket.delete(id);
} catch (e) {
  if (e instanceof MongoRuntimeError && /File not found/.test(e.message)) {
    // treat as idempotent success
  } else throw e;
}

Prevention

When it happens

Trigger: Calling bucket.delete(id) for an id that was never uploaded or was already deleted. Passing a string id where an ObjectId is expected, or an ObjectId from a different bucket/database.

Common situations: Retry/idempotency logic calling delete twice. Stale id cached from a previous session. Using the wrong bucket instance (custom bucketName) so the files collection differs.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11). Data as JSON: /api/errors/3ea39a78825c6de4. Report an issue: GitHub.

Appendix: source

Thrown at src/gridfs/index.ts:187

        serverSelectionTimeoutMS: this.s.db.client.s.options.serverSelectionTimeoutMS
      });
    }

    const { deletedCount } = await this.s._filesCollection.deleteOne(
      { _id: id },
      { timeoutMS: timeoutContext?.remainingTimeMS }
    );

    const remainingTimeMS = timeoutContext?.remainingTimeMS;
    if (remainingTimeMS != null && remainingTimeMS <= 0)
      throw new MongoOperationTimeoutError(`Timed out after ${timeoutMS}ms`);
    // Delete orphaned chunks before returning FileNotFound
    await this.s._chunksCollection.deleteMany({ files_id: id }, { timeoutMS: remainingTimeMS });

    if (deletedCount === 0) {
      // TODO(NODE-3483): Replace with more appropriate error
      // Consider creating new error MongoGridFSFileNotFoundError
      throw new MongoRuntimeError(`File not found for id ${id}`);
    }
  }

  /** Convenience wrapper around find on the files collection */
  find(filter: Filter<GridFSFile> = {}, options: FindOptions = {}): FindCursor<GridFSFile> {
    return this.s._filesCollection.find(filter, options);
  }

  /**
   * Returns a readable stream (GridFSBucketReadStream) for streaming the
   * file with the given name from GridFS. If there are multiple files with
   * the same name, this will stream the most recent file with the given name
   * (as determined by the `uploadDate` field). You can set the `revision`
   * option to change this behavior.
   */
  openDownloadStreamByName(
    filename: string,
    options?: GridFSBucketReadStreamOptionsWithRevision

View on GitHub (pinned to dce7939f86)