Lock in $67
TROUBLESHOOTING

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.

Espen Opdahl Published 5 min read
The short answer

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.

worth knowing The tool named "get errors" does not report ad rejections.

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 deliveryYes — this is the whole job—
The ad was rejected in reviewNamed as out of scopeeffective_status = DISAPPROVED
The ad account is disabled or restrictedNamed as out of scopeThe account listing, not this tool
Underdelivery, pacing, learning limitedNamed as out of scopeNot an error at all — a performance question
Still waiting on reviewNot stated either wayeffective_status = PENDING_REVIEW
No valid billing on fileNot stated either wayeffective_status = PENDING_BILLING_INFO
A catalog, feed or product-set problemSurfaces, but as a pointerThe 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.

One symptom "My ad is not running" Three different lookups Hard stop on publish or delivery ads_get_errors Rejected, on hold, or unbilled effective_status The account itself is the problem the account listing Only the green box is in scope for the errors tool. Read off the live tool schema, 26 August 2026.

How to ask whether anything is broken

  1. 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.

  2. 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.

  3. 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.

  4. 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 price

Pre-sale: the modules are still being recorded and founding members get the checkout link first. No charge today. Public price $97.

Espen Opdahl Writes The Claude Ads Operator. I run Meta ad accounts through Claude and Meta's official ads connector, and I write down what actually happens — including the parts that don't work. Not affiliated with Meta or Anthropic.