Error 100 is the widest net in the WhatsApp Cloud API. Meta documents it as "Invalid parameter" with an HTTP status of 400, and the recommended action is to verify your request formatting meets the endpoint's requirements and check parameter spelling (Meta for Developers, WhatsApp error codes reference, retrieved 2026-08-17).
Because it covers any structurally wrong request, error 100 is the code you get when you have made a mistake Meta has no more specific code for. That makes it frustrating and also fast to fix, provided you read the right field. Almost every error 100 response carries an error_data.details string that names the offending parameter, and most teams never look at it.
This guide covers how to read the response, the eight causes that account for the overwhelming majority of real error 100 traffic, and a pre-send validation approach that stops them reaching Meta. For the wider failure surface, our WhatsApp Business API error codes reference indexes the rest.
How to Read an Error 100 Response
The generic form tells you very little:
{
"error": {
"message": "(#100) Invalid parameter",
"type": "OAuthException",
"code": 100,
"fbtrace_id": "AbCdEfGhIjK"
}
}The useful form carries error_data, and Meta populates it far more often than most integrations bother to log:
{
"error": {
"message": "(#100) Invalid parameter",
"type": "OAuthException",
"code": 100,
"error_data": {
"messaging_product": "whatsapp",
"details": "Param template must be an object."
},
"error_subcode": 2494010,
"fbtrace_id": "AbCdEfGhIjK"
}
}details here says exactly what is wrong. Log the whole error object, not error.message, and most error 100 investigations become a five-second read. If your logging pipeline truncates nested objects, that alone is costing your team hours.
Note the type is still OAuthException, which is a quirk of the Graph API rather than a hint that credentials are involved. A genuine credential problem returns error 0 or error 190 instead.
The Eight Most Common Causes
# | Cause | Typical | Fix |
|---|---|---|---|
1 | Missing | "Param messaging_product is required" | Add |
2 | Wrong | "Param type must be one of..." | Use a supported value for the message type |
3 | Object sent as string | "Param template must be an object" | Send JSON structure, not a serialised string |
4 | Phone number ID vs phone number | Varies | Use the numeric phone number ID in the URL path |
5 | Wrong API version in the path | "Unsupported get request" or similar | Use a currently supported version |
6 | Malformed recipient number | Varies | E.164, digits only, no plus or separators |
7 | Unsupported field for the message type | "Param X is not expected" | Remove fields the type does not accept |
8 | Invalid or expired media ID | Varies | Re-upload the media and use the returned ID |
Cause 1: messaging_product is missing
Every message send to the Cloud API requires this field, and it must be the string whatsapp. It is easy to miss because it looks like boilerplate rather than a parameter:
{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "text",
"text": { "body": "Your order has shipped." }
}Omit it and you get error 100 with no obvious cause, which is why this dominates the error 100 traffic of newly built integrations. Add it to your request builder as a constant rather than a per-call argument, so it cannot be forgotten.
Cause 2 and 3: structural type mistakes
type must match one of the message types the endpoint accepts, and the corresponding object must be present and correctly nested. Two failure patterns recur:
Declaring one type and supplying another object, for example "type": "text" alongside a template object. And serialising the nested object to a string before sending, which happens when a template payload is built as text and interpolated, or when an HTTP client double-encodes the body. details reporting that a param "must be an object" is the signature of the second case.
Cause 4: the wrong identifier in the URL
The send endpoint takes the phone number ID, a numeric identifier from the Meta dashboard, not the phone number itself:
POST https://graph.facebook.com/v23.0/{PHONE_NUMBER_ID}/messages
Putting 919876543210 where PHONE_NUMBER_ID belongs produces error 100 or a 404 depending on the path. This bites hardest for businesses running multiple numbers on one WhatsApp Business Account, where several IDs are in play and the mapping between them and the display numbers has to be stored deliberately.
Cause 5: an unsupported API version
Graph API versions are deprecated on a schedule. A pinned version that has passed end of life starts failing, often with error 100 rather than a clear deprecation message. Pin a version explicitly rather than omitting it, keep the value in configuration rather than scattered through the codebase, and diary the deprecation date.
Cause 6: a malformed recipient number
The to field expects E.164 without the plus sign: country code followed by the subscriber number, digits only. A number that is malformed enough to be structurally invalid returns error 100. A number that is well-formed but unreachable returns error 131026 instead. That distinction is a useful diagnostic: error 100 on a recipient field means the string is wrong, not the person.
Cause 7: fields the message type does not accept
Each message type accepts a defined field set. Sending a preview_url flag on a media message, or button components on a template that has none, gets the whole request rejected rather than the extra field ignored. Build payloads per type instead of assembling one superset object and hoping unused keys are tolerated.
Cause 8: an invalid media ID
Uploaded media IDs are not permanent. A cached ID reused after its lifetime, an ID from a different phone number's upload, or an ID from a failed upload all produce error 100 on send. Upload media as part of the send flow rather than reusing IDs across long-lived campaigns, and treat a media ID as a short-lived handle rather than a stored asset reference.
Why You Should Never Retry Error 100
Error 100 is deterministic. The same payload will be rejected identically every time, because nothing about your account, your limits, or the recipient is involved. Retrying achieves nothing except consuming request budget, and at volume it can push you into rate limit errors on top of the original defect.
The correct handling is a dead-letter queue. Capture the full error object with the fbtrace_id and the outbound payload, alert on volume, and fix the payload builder. This is the opposite of the correct handling for a transient 500-class failure, which is why bucketing all WhatsApp errors into one retry policy causes trouble.
Two habits prevent most error 100 traffic reaching Meta at all.
Validate before sending. A JSON schema per message type, checked in your own code, catches missing messaging_product, wrong type values, and unexpected fields at build time rather than at Meta's edge. It also gives you an error message that names your field rather than Meta's parameter.
Test payload shapes in a staging WABA. A separate WhatsApp Business Account for integration testing lets you exercise every message type against real API validation without touching production traffic or your production quality signals. Our WhatsApp API integration guide covers how to structure that environment split.
One note on ownership: because error 100 is purely structural, it is genuinely a developer-owned error, unlike most codes in this cluster. It has no policy dimension, no billing consequence, and no effect on your quality rating. If error 100 is appearing in production, the gap is in payload validation and error logging, not in how the business uses WhatsApp.
Frequently Asked Questions
What does WhatsApp API error 100 mean?
Meta documents error 100 as "Invalid parameter" with HTTP status 400. It means the request was structurally wrong: a required field was missing, a value was of the wrong type, a parameter was misspelled, or a field was included that the endpoint does not accept for that message type. Your credentials and account were not the problem.
How do I find which parameter is invalid?
Read error.error_data.details in the response body. Meta usually names the offending parameter there, for example "Param template must be an object" or "Param messaging_product is required." Most integrations log only error.message, which is generic, and that is why error 100 gets a reputation for being undebuggable.
Why do I get error 100 when the request looks correct?
Check messaging_product first, since it is required on every send and easy to omit. Then confirm you are using the numeric phone number ID in the URL path rather than the phone number itself, that your pinned Graph API version is still supported, and that nested objects are being sent as JSON structures rather than serialised strings.
Should I retry a request that failed with error 100?
No. The failure is deterministic, so an unchanged payload fails identically every time. Send it to a dead-letter queue with the full error object and fbtrace_id, alert on volume, and fix the payload builder. Retry logic belongs on transient failures, not on malformed requests.
What is the difference between error 100 and error 131009?
Both concern parameter problems. Error 100 covers structural invalidity, such as a missing required field or a value of the wrong type. Error 131009 is more specific to an invalid parameter value being supplied where the structure was acceptable. In practice, read error_data.details in both cases, because that field is more informative than the code itself.
Does error 100 affect my quality rating or cost me anything?
No. The request was rejected at validation with a 400 before any message was created, so no message was delivered, nothing was billed under the per-message pricing model Meta introduced on 1 July 2025, and no user-facing signal was generated.
Log the Whole Error, Fix the Builder
Error 100 has a reputation for being vague that it does not really deserve. Meta names the offending parameter in error_data.details most of the time; the information is discarded by logging pipelines that capture only the top-level message. Fixing that one logging gap converts your hardest WhatsApp error into your easiest.
After that, the work moves upstream. Schema validation per message type, messaging_product as a constant rather than an argument, phone number IDs stored deliberately, and a pinned API version you actually track will keep error 100 out of production entirely.
Prefer not to maintain payload validation yourself? Helo.ai is a Meta Partner and exposes a validated messaging layer over the Cloud API, so malformed payloads are caught in your own stack rather than at Meta's edge. Talk to an expert.
Next: error 132000 if the invalid parameter turns out to be a template variable, or error 0 if the failure is authentication rather than structure.




