ads_get_errors: what Meta's connector reports, and what it skips
The connector has a tool built for this exact question. Read what it excludes before you trust a quiet answer from it.
Meta's official ads connector has a tool for this, and it is narrower than its
name. Point ads_get_errors at an ad account ID and it returns delivery-blocking
errors for the campaigns, ad sets and ads underneath — not for the account itself. Its own
description rules out three categories by name: performance, pacing and optimisation issues;
disabled or restricted accounts; and ad rejection. So an empty answer is not a clean bill of health.
It is silence about one narrow slice of "not running".
An ad set is not spending. You ask Claude whether anything is broken, it runs the tool that exists for exactly that, and reports nothing. Twenty minutes later you open Ads Manager out of habit and there is a red icon in the delivery column.
Both answers are true. "Is anything broken" has three separate homes inside this connector and the errors tool owns one of them. Knowing which one is the difference between a quiet answer you can trust and a quiet answer that means the question went elsewhere.
What the tool actually is
It takes a list of entity IDs — campaign, ad set, ad, or ad account — and accepts several at once, which is the genuinely useful bit for anyone holding more than one account.
The account-level behaviour is worth reading twice. Verbatim from the tool's own description:
If account ID is provided, it returns all errors of its child ad entities, but not the account itself.
So the sweep you would naturally reach for — hand it the account, ask what is wrong — cannot report that the account is the thing that is wrong. A billing failure, a restriction, a hold on the account itself: out of scope by construction. And if the account has stopped answering queries at all, you get neither the parent nor the children.
When there is nothing to report, this is what comes back:
{"errors": "[]"}
An empty list, delivered as a string rather than as an array — a non-event if you are reading the reply in a chat window, a real one if something downstream is parsing it. I ran it on 26 August 2026 against live ad accounts, singly and then every ID in one call, and got that same response each time.
Read off the live tool description on 26 August 2026, which names three things it does not cover: "performance, pacing, or optimization issues", "Disabled or restricted accounts" and "Ad rejection". The last matters most: a rejected ad is what most people mean when they say their ad has an error. Meta's April 2026 announcement page does not enumerate the tools and says nothing about delivery errors, so the tool schema is the only description of this behaviour I could find anywhere.
Where each kind of "error" actually lives
Three of the rows below are the connector telling you in its own words that it will not answer. The rest is what the field-metadata tool reports as selectable and filterable at campaign, ad set and ad level.
| What you meant by "error" | Does ads_get_errors cover it? | Where to look instead |
|---|---|---|
| A hard stop that blocks publish or delivery | Yes — this is the whole job | — |
| The ad was rejected in review | Named as out of scope | effective_status = DISAPPROVED |
| The ad account is disabled or restricted | Named as out of scope | The account listing, not this tool |
| Underdelivery, pacing, learning limited | Named as out of scope | Not an error at all — a performance question |
| Still waiting on review | Not stated either way | effective_status = PENDING_REVIEW |
| No valid billing on file | Not stated either way | effective_status = PENDING_BILLING_INFO |
| A catalog, feed or product-set problem | Surfaces, but as a pointer | The catalog diagnostics tools it names |
That catalog row is a design choice worth noticing. The tool description instructs the assistant that when an error mentions a product set, a catalog, a feed or product eligibility, it should go to the catalog diagnostics and dynamic-ads health tools on the backing catalog for the root cause. The error text is a signpost, not a diagnosis — and unfollowed, it is a symptom and a dead end.
Most of the value here is knowing which question to ask before you trust the answer to it. See what the weekly routine checks →
The status field does the work the errors tool won't
Ask the connector's field-metadata tool about effective_status and it describes
itself as the actual delivery status, which can differ from the status you set because it accounts
for parent state, ad review, billing and budget conditions. It is filterable and sortable at
campaign, ad set and ad level, and its values include WITH_ISSUES,
DISAPPROVED, PENDING_REVIEW and PENDING_BILLING_INFO.
A second field, delivery, is coarser and easier to prompt with: an enum running
draft, pending, active, inactive, error, deleted, completed and off. Filtering on error
gets you the entities to hand to ads_get_errors. Between them you can find everything
the errors tool is not allowed to mention.
One field that does not exist here is worth flagging. issues_info — the
field the Marketing API uses to carry delivery diagnostics on an ad — comes back from the connector's
field-metadata tool under unknown_fields. You cannot pull error detail as a column
alongside spend. It is always a second call.
How to ask whether anything is broken
-
Ask for the status column before the errors START HERE
"Show every ad set with its configured status and its effective status" gets the rejections, the review holds and the billing stops in one table — the categories the errors tool declines. Do it first and the errors call becomes a follow-up on a short list rather than a blind sweep. The trade: a table to read rather than a yes-or-no, padded with ordinary paused rows you have to look past.
-
Then run the errors tool on the account ID
This is the cheap sweep and worth having — pass every account ID you manage in one call. Read the empty answer for what it is: nothing found among the child entities, in the one category covered. The trade: it can never report a problem with the account itself, so a suspended account and a healthy one produce the same empty list.
-
Chase catalog wording to the catalog tools
If an error mentions a feed, a product set or product eligibility, that string is the start of the diagnosis, not the end. Catalog diagnostics, dynamic-ads health, data sources and feed uploads each have their own tool.
-
Confirm the fix in Ads Manager, not in the chat
An error that has cleared and an error the tool was never going to mention look identical from here. One look at the delivery column closes the loop — the same habit that catches a metric reporting nothing as null.
An empty error list means nothing was found in the one place the tool is allowed to look.
- Treating a clean sweep as an all-clear. Three categories of stoppage are excluded by name, and the reply never mentions it.
- Running it on the account and expecting account news. The description is explicit that the account itself is excluded, so a suspended one answers exactly like a healthy one.
- Asking about "errors" when you mean underdelivery. Pacing and learning problems are not errors here, so you get a confident nothing.
- Stopping at the error string. For anything catalog-shaped it points at a different tool, and a symptom copied out of a chat window is not a diagnosis.
Try this tonight
Ask for every ad in the account with its effective status, then run the errors tool on the same
account ID, and put the two answers side by side. Anything sitting in DISAPPROVED or
PENDING_REVIEW that the errors call did not mention is tomorrow morning's list — fixable
today, and otherwise invisible.
This is one entry in a long manifest; the rest is in the full tools list. Not connected yet? Start with the setup.
Frequently asked questions
Does an empty result mean my account is healthy?
No. It means no delivery-blocking error was found on the child entities. Rejections, account-level restrictions and underdelivery are excluded by the tool's own description, so they could not have appeared either way.
Can I see the reason an ad was rejected?
Not through this tool. The connector will report an effective status of DISAPPROVED, which is the fact you act on. The policy detail behind it lives in Ads Manager, which is where the appeal is anyway.
Is it safe to let Claude run this on its own?
Yes — it is a read. It fetches and returns, changes nothing, and cannot pause, publish or spend. Same class as any other reporting call, which is the class you can leave unsupervised.
Why is the empty result a string and not an array?
I do not know and I have not found it documented. It was consistent across every call I made on 26 August 2026, so it reads as serialisation rather than a fault. It only matters if something downstream parses the reply.
The routine that asks the right question first
Ten modules on running Meta ads through Claude, including the weekly check that reads status before it reads errors.
See what's inside — $67 founding pricePre-sale: the modules are still being recorded and founding members get the checkout link first. No charge today. Public price $97.