How to fix INVALID_ARGUMENT: Value for argument 'document' is invalid in Firebase

FirebaseINTERMEDIATEMEDIUMUpdated Dec 22, 2025ยท 110 views

This Firebase Firestore error occurs when setDoc() or updateDoc() receives invalid data in the document parameter. The document must be a plain JavaScript object. Fix it by ensuring you're passing a valid plain object and not a DocumentReference, class instance, or malformed data.

Quick fix

Fixes INVALID_ARGUMENT

  1. Ensure you're passing a plain object, not a DocumentReference
  2. Convert class instances to plain objects
  3. Remove undefined values from document objects
  4. Fix DocumentSnapshot usage in setDoc()
  5. Verify document size is under 1 MiB
firebase โ€” error
# INVALID_ARGUMENT: Value for argument 'document' is invalid
INVALID_ARGUMENT: Value for argument 'document' is invalid

What this error means

The "INVALID_ARGUMENT: Value for argument 'document' is invalid" error in Firebase Firestore indicates that the data you're trying to write doesn't meet Firestore's validation requirements. When you call setDoc() or updateDoc(), the second parameter must be a plain JavaScript object containing the fields you want to set. Firestore validates that the document data: - Is a plain object (not a class instance, DocumentReference, or circular reference) - Contains only valid Firestore data types (strings, numbers, booleans, dates, arrays, maps, etc.) - Doesn't exceed size limits (document size must be under 1 MiB) - Has valid field names (no undefined values in root object) When validation fails, Firestore throws this INVALID_ARGUMENT error to prevent corrupting your database with malformed data.

Typical symptoms

  • setDoc() or updateDoc() fails with INVALID_ARGUMENT error
  • Error message mentions "document" parameter is invalid
  • Code that previously worked suddenly fails after SDK update
  • Error occurs when trying to save form data or complex objects
  • updateDoc() works but setDoc() fails with same object
  • Error appears in console or server logs during write operations

Common causes

  1. Passing a DocumentReference object instead of plain data to setDoc()
  2. Using a class instance (created with new keyword) instead of plain object
  3. Including undefined values in the document object at root level
  4. Document size exceeds 1 MiB limit (too much data)
  5. Using DocumentReference in nested fields without merge:true for updateDoc()
  6. Passing DocumentSnapshot instead of snapshot.data() in setDoc()
  7. Circular reference in object causing serialization failure
  8. Using non-serializable objects like Functions, Symbols, or Promises
  9. Mixing Firebase types from different SDK versions or packages

How to fix "INVALID_ARGUMENT: Value for argument 'document' is invalid"

1Ensure you're passing a plain object, not a DocumentReference

The most common cause is accidentally passing a DocumentReference instead of data:

WRONG - passing DocumentReference directly:
const docRef = doc(db, 'users', 'user123');
await setDoc(docRef); // ERROR: document is missing data

CORRECT - pass DocumentReference as first parameter, data as second:
const docRef = doc(db, 'users', 'user123');
const userData = { name: 'John', email: 'john@example.com' };
await setDoc(docRef, userData);

WRONG - DocumentReference in data object:
const userRef = doc(db, 'users', 'user123');
const postData = {
title: 'My Post',
author: userRef // ERROR: DocumentReference not allowed here
};
await setDoc(doc(db, 'posts', 'post1'), postData);

CORRECT - use documentId field instead:
const postData = {
title: 'My Post',
authorId: 'user123' // Store just the ID
};
await setDoc(doc(db, 'posts', 'post1'), postData);

Or to store a reference for cross-referencing:
const postData = {
title: 'My Post',
author: 'user123' // Store as string ID
};
await setDoc(doc(db, 'posts', 'post1'), postData);

2Convert class instances to plain objects

If using a class, convert to plain object before sending to Firestore:

WRONG - passing class instance:
class User {
constructor(name, email) {
this.name = name;
this.email = email;
}
greet() {
return Hello ${this.name};
}
}

const user = new User('John', 'john@example.com');
await setDoc(doc(db, 'users', 'user1'), user); // ERROR: class instance not allowed

CORRECT - convert to plain object:
// Method 1: Use object spread
const userPlain = {
name: user.name,
email: user.email
};
await setDoc(doc(db, 'users', 'user1'), userPlain);

// Method 2: Use JSON serialization
const userPlain = JSON.parse(JSON.stringify(user));
await setDoc(doc(db, 'users', 'user1'), userPlain);

// Method 3: Create plain object directly
const userData = {
name: 'John',
email: 'john@example.com'
};
await setDoc(doc(db, 'users', 'user1'), userData);

// With TypeScript and interfaces:
interface IUser {
name: string;
email: string;
}

const userData: IUser = {
name: 'John',
email: 'john@example.com'
};
await setDoc(doc(db, 'users', 'user1'), userData);

3Remove undefined values from document objects

Firestore doesn't allow undefined values in the root object:

WRONG - undefined value in root:
const userData = {
name: 'John',
middleName: undefined, // ERROR: undefined not allowed
email: 'john@example.com'
};
await setDoc(doc(db, 'users', 'user1'), userData);

CORRECT - remove undefined values:
// Method 1: Use Object.fromEntries with filter
const userData = {
name: 'John',
middleName: undefined,
email: 'john@example.com'
};

const cleanData = Object.fromEntries(
Object.entries(userData).filter(([_, v]) => v !== undefined)
);
await setDoc(doc(db, 'users', 'user1'), cleanData);

// Method 2: Explicit fields only
const userData = {
name: 'John',
email: 'john@example.com'
// middleName omitted entirely
};
await setDoc(doc(db, 'users', 'user1'), userData);

// Method 3: Helper function for form data
function cleanFormData(data) {
return Object.fromEntries(
Object.entries(data)
.filter(([_, value]) => value !== undefined && value !== null && value !== '')
);
}

const formData = {
name: 'John',
middleName: '',
email: 'john@example.com'
};

await setDoc(doc(db, 'users', 'user1'), cleanFormData(formData));

4Fix DocumentSnapshot usage in setDoc()

If copying data from another document, use .data() method:

WRONG - passing entire snapshot:
const sourceDoc = await getDoc(doc(db, 'users', 'source'));
await setDoc(doc(db, 'users', 'copy'), sourceDoc); // ERROR: snapshot is not plain object

CORRECT - extract data from snapshot:
const sourceDoc = await getDoc(doc(db, 'users', 'source'));
if (sourceDoc.exists()) {
await setDoc(doc(db, 'users', 'copy'), sourceDoc.data());
}

// Or with type checking:
const sourceDoc = await getDoc(doc(db, 'users', 'source'));
const data = sourceDoc.data();
if (data) {
await setDoc(doc(db, 'users', 'copy'), data);
}

// Merging with existing document:
const sourceData = (await getDoc(doc(db, 'users', 'source'))).data() || {};
await setDoc(
doc(db, 'users', 'copy'),
sourceData,
{ merge: true } // Merge with existing fields
);

5Verify document size is under 1 MiB

If document is very large, it may exceed Firestore's 1 MiB limit:

// Check document size before writing:
function getDocumentSize(doc) {
return new Blob([JSON.stringify(doc)]).size; // Size in bytes
}

const userData = {
name: 'John',
largeData: '...' // Large string
};

const sizeInBytes = getDocumentSize(userData);
const sizeInMiB = sizeInBytes / (1024 * 1024);

console.log(Document size: ${sizeInMiB.toFixed(2)} MiB);

if (sizeInMiB > 1) {
console.error('Document exceeds 1 MiB limit');
// Solution: Split into multiple documents or use Cloud Storage
}

// Split large data into separate documents:
const mainData = {
name: 'John',
email: 'john@example.com'
};

const largeData = {
content: '...' // Large content
};

// Write to separate docs
await setDoc(doc(db, 'users', 'user1'), mainData);
await setDoc(doc(db, 'user_data', 'user1_content'), largeData);

// For very large files (videos, large documents):
// Use Cloud Storage instead
import { ref, uploadBytes } from 'firebase/storage';

const largeFile = new File(['...'], 'largefile.bin');
const storageRef = ref(storage, 'uploads/user1/largefile');
await uploadBytes(storageRef, largeFile);

// Reference the storage file from Firestore:
const userData = {
name: 'John',
fileUrl: 'gs://bucket/uploads/user1/largefile'
};
await setDoc(doc(db, 'users', 'user1'), userData);

6Handle non-serializable types properly

Ensure all values can be serialized to JSON:

WRONG - using non-serializable types:
const userData = {
name: 'John',
callback: () => console.log('test'), // ERROR: Function not allowed
regex: /test/g, // ERROR: RegExp not allowed
symbol: Symbol('test'), // ERROR: Symbol not allowed
promise: Promise.resolve() // ERROR: Promise not allowed
};
await setDoc(doc(db, 'users', 'user1'), userData);

CORRECT - use serializable values:
// For Dates - Firestore has native Date support:
const userData = {
name: 'John',
createdAt: new Date() // Converted to Timestamp automatically
};
await setDoc(doc(db, 'users', 'user1'), userData);

// For custom objects, convert to JSON:
const userData = {
name: 'John',
config: JSON.stringify(complexObject) // Store as string
};
await setDoc(doc(db, 'users', 'user1'), userData);

// Using Firestore Timestamp for dates:
import { Timestamp } from 'firebase/firestore';

const userData = {
name: 'John',
createdAt: Timestamp.now()
};
await setDoc(doc(db, 'users', 'user1'), userData);

// For arrays with mixed types, ensure all elements are serializable:
WRONG:
const data = {
items: [1, 'text', { valid: true }, () => {}] // Function not allowed
};

CORRECT:
const data = {
items: [
{ type: 'number', value: 1 },
{ type: 'text', value: 'text' },
{ type: 'object', value: { valid: true } }
]
};

Advanced notes

### DocumentReference Cross-References

If you need to store references between documents, there are several approaches:

1. Store IDs (recommended for most cases):

javascript
// Store just the ID
const postData = {
  title: 'My Post',
  authorId: userId // String ID
};
await setDoc(doc(db, 'posts', 'post1'), postData);

// Query by author:
const posts = await getDocs(
  query(collection(db, 'posts'), where('authorId', '==', userId))
);

2. Use subcollections for hierarchical relationships:

javascript
// Store comment under post's subcollection
const commentData = { text: 'Great post!', authorId: userId };
await setDoc(
  doc(db, 'posts', 'post1', 'comments', 'comment1'),
  commentData
);

3. Use map fields for embedded data:

javascript
const postData = {
  title: 'My Post',
  author: {
    id: userId,
    name: 'John'
  }
};
await setDoc(doc(db, 'posts', 'post1'), postData);

### SDK Version Compatibility

This error can occur when using Firestore types from different SDK versions. Ensure consistency:
- Don't mix @firebase/firestore with older firebase packages
- Update all Firebase packages together
- For React Native, use @react-native-firebase/firestore
- For Flutter, use cloud_firestore package from the official Firebase team

### Type Safety with TypeScript

Define interfaces to catch type errors at compile time:

typescript
interface UserData {
  name: string;
  email: string;
  createdAt: Date;
  metadata?: Record<string, string>;
}

const userData: UserData = {
  name: 'John',
  email: 'john@example.com',
  createdAt: new Date()
};

await setDoc(doc(db, 'users', 'user1'), userData);

Frequently asked questions

What does "INVALID_ARGUMENT" mean?
The "INVALID_ARGUMENT: Value for argument 'document' is invalid" error in Firebase Firestore indicates that the data you're trying to write doesn't meet Firestore's validation requirements. When you call setDoc() or updateDoc(), the second parameter must be a plain JavaScript object containing the fields you want to set. ) - Doesn't exceed size limits (document size must be under 1 MiB) - Has valid field names (no undefined values in root object) When validation fails, Firestore throws this INVALID_ARGUMENT error to prevent corrupting your database with malformed data.
How do I fix "INVALID_ARGUMENT"?
This Firebase Firestore error occurs when setDoc() or updateDoc() receives invalid data in the document parameter. The document must be a plain JavaScript object. Fix it by ensuring you're passing a valid plain object and not a DocumentReference, class instance, or malformed data.
What causes "INVALID_ARGUMENT"?
Passing a DocumentReference object instead of plain data to setDoc() Using a class instance (created with new keyword) instead of plain object Including undefined values in the document object at root level
Is the "INVALID_ARGUMENT" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading