Skip to main content

Fix Meta Catalog Row-Level Validation Errors

By Marius Pahomi · Published 2026-08-17 · Last updated 2026-08-29

Meta validates product feeds row by row: when any single field in a row is malformed, Commerce Manager rejects the entire row and that product silently drops out of your catalog. The classic trigger is the applink family — the optional deep-link columns (applink.ios_url, applink.android_url, applink.android_package, applink.ipad_url and their siblings) that many feeds inherit from an old template. The columns are optional, but once present they must be valid: Android deep links require applink.android_package, and every other platform requires a well-formed URL. A single empty applink cell or a stale app-store identifier therefore invalidates every row that carries it, which is why the error often reads as if deep link validation failed on all platforms at once.

The recovery loop is short once you know where to look. Read the exact issue in Commerce Manager under Catalog, then Data Sources; locate the offending column in your source file; decide whether to repair the deep-link values or remove the columns entirely — removal is usually correct, because Meta reads deep links automatically from the App Links metadata on your product pages; regenerate and re-upload the feed; and verify that the ingested product count matches your source row count again.

This guide walks that loop end to end: how row-level validation actually behaves, why applink is the most common trigger, what the "all platforms rejected" variant means, which other fields can reject whole rows, and how to stop the same rejection from returning on the next scheduled fetch.

Validate your feed with FeedArc free — catch these errors before you upload.

How Meta validates product feeds row by row

One malformed field rejects the whole row

Meta ingests a product feed line by line, and validation is all-or-nothing per row. If any field in a row fails validation — a deep-link URL that is not a URL, an Android applink without its package name, a price without a parseable value — the row is rejected and the product it describes drops from the catalog. This is by design: Meta would rather skip a product than ingest partially broken data that could surface a dead link inside a shopping surface. The practical consequence is that a purely optional column can take healthy products offline. Nothing about the product itself has to be wrong; one malformed cell in a column you may not even use is enough. That asymmetry — optional column, mandatory correctness — is what makes row-level validation surprising the first time it rejects half a catalog.

Rejected rows fail quietly, not loudly

Unlike Google Merchant Center, which lists each disapproved item with a named issue on its Diagnostics page, a rejected Meta row simply does not enter the catalog. Commerce Manager records the ingestion issue against the data source — typically an "invalid field" message naming the column — but the products themselves just go missing. If you track catalog size, the symptom is a product count that is suddenly lower than your source row count after an upload. If you do not track it, the first signal is often downstream: ads sets shrink, a product no longer appears in the shop, or a promoted item stops serving. Treat any gap between rows submitted and products ingested as a validation failure to investigate, not as a synchronisation delay that will resolve itself.

Limitations
  • Row-level validation covers structural correctness only — a row that passes validation can still be rejected later by policy review (for example prohibited content), which is a separate mechanism with separate messaging.

What the applink column family contains

The applink columns carry per-platform deep links so that a product tapped inside Facebook or Instagram can open directly in your native app instead of the mobile web. The family per Meta’s catalog reference: applink.ios_url, applink.ios_app_store_id, applink.ios_app_name, applink.android_url, applink.android_package, applink.android_app_name, plus the iPad, iPhone, and Windows Phone variants of the same triplet. All of them are optional. But the moment a row carries any applink value, that value must validate: Android requires applink.android_package to be present, and every other platform requires the URL field to be a valid URL. An applink column that exists but is empty, half-filled, or carries a placeholder fails exactly those checks.

How broken applink data gets into feeds

Almost nobody types applink values by hand. They arrive by inheritance: a feed template copied from a project that had a native app, an export preset in an old tool that emitted the columns by default, or a migration that carried every historical column across. The app the links pointed to then changes or disappears — the app-store ID goes stale, the URL scheme is renamed — and the columns keep shipping with every upload. Because validation is row-level, the damage scales with column coverage: if the applink columns are populated (even with empty strings) on every row, every row fails, which is precisely the catalog-wide rejection pattern that reads as a total feed failure rather than what it is — one inherited column family that no longer validates.

Limitations
  • This guide covers applink as feed columns. Deep links delivered through App Links metadata in your page markup are validated by Meta’s crawler on a different path and are not subject to feed row rejection.

Reading the "all platforms rejected" error

Why every platform fails at the same time

The error variant that sends people searching — deep link validation rejected on all platforms — looks dramatic but has a mundane mechanic. The per-platform applink fields are usually generated from the same source template: the same base URL with a scheme swapped, or the same spreadsheet columns filled by the same export step. When that shared source is malformed, iOS, iPad, Android, and Windows Phone values are all malformed in the same way, so validation reports a failure on each platform it checked. Seeing every platform rejected is therefore evidence for a single upstream cause, not four independent problems. Fix the source — or remove the columns — and all platforms clear together.

Confirming the diagnosis in your source file

Open the actual file your data source fetches — not the tool that generates it — and inspect the header row. Three findings confirm the applink diagnosis. First: applink columns exist at all, when your business has no native app; they should not be there. Second: an applink.android_url column exists without an accompanying applink.android_package column — Android’s hard requirement is unmet for every row that has a value. Third: the columns exist and are empty strings rather than absent — present-but-empty is what trips validation, absence is what you want. Column-level inspection beats scrolling rows, because the failure is almost always structural (the column set) rather than value-by-value.

Repair or remove: the applink decision

Removal is the default answer

If you do not have a live native app — or you have one but did not deliberately set up feed-level deep links — remove the applink columns entirely. Per Meta’s product feeds documentation, deep links are picked up automatically from the App Links metadata on your product pages, and feed-level applink values exist to override that crawled data when you actively need to. Dropping the columns is therefore safe: you lose nothing that page markup does not already provide, and you eliminate the entire class of row rejections in one edit. Keep deep links in your page markup, keep the feed lean. This is also the honest engineering read of the situation: columns nobody maintains are a liability, not a feature.

When keeping feed-level applink is right

Feed-level applink earns its place in one situation: you have a native app and you need per-product deep links that differ from what your page markup declares — for example, the app’s product route uses internal identifiers that the public page does not expose. In that case, repair rather than remove: populate the full platform triplet you target (URL, store identifier, app name), guarantee applink.android_package is present wherever any Android value is, and generate the values from the same catalog source as the rest of the row so they cannot drift independently. Then validate the columns on every regeneration — feed-level applink takes precedence over crawled metadata, so a mistake here overrides working page-level deep links with broken ones.

Limitations
  • Removing applink columns fixes feed rejection; it does not verify that your page-level App Links metadata is present or correct. If in-app deep linking matters to your ads, audit the page markup separately.
  • Precedence means feed values win over crawled metadata — there is no merge. Partial feed-level applink data does not fall back per-field to page markup.

Other fields that reject whole rows

Prices, availability, and identifiers

Applink is the classic trigger, not the only one. The price field must carry a parseable amount with its ISO currency — 139.00 USD, not a bare number in one row and a symbol-prefixed string in the next. The availability value must come from Meta’s accepted list — in stock works; a home-grown status like “5 left” does not. And id must be present and unique per row: the row identity everything else keys on, including the Conversions API match between server-side events and catalog items. Each of these fails the same way applink does — the row is rejected whole, regardless of how correct the remaining thirty columns are.

URLs and images

The link and image_link fields must be well-formed absolute URLs. The recurring traps are relative paths emitted by a platform export, whitespace or unescaped characters inside the URL, and placeholder values like N/A that a spreadsheet filled into empty cells. Meta additionally enforces image minimums (500×500 pixels for catalog images), so a syntactically valid image_link can still surface an image-quality issue after ingestion — but a malformed one never gets that far, because the row is rejected at validation. When auditing a rejected feed, check URL columns with the same column-level eye as applink: if the generator produced one malformed URL, it usually produced many, in the same shape.

Limitations
  • The examples here are the high-frequency triggers, not an exhaustive field list — Meta’s catalog fields reference documents the full per-field requirements and stays authoritative as the spec evolves.

Diagnosing rejections in Commerce Manager

Where the errors actually live

In Commerce Manager, open your catalog, then Data Sources, and select the feed that uploaded last. The ingestion report for each fetch lists what Meta accepted and what it flagged, with "invalid field" issues naming the offending column — this is where the applink diagnosis is usually confirmed in one line. Two numbers matter more than any single message: rows in your source file versus products ingested. Equal numbers with an error message means a value-level warning; a shortfall means row rejections, and the size of the shortfall tells you whether the trigger is a universal column (everything missing) or a subset of rows (only some products carry the bad value). Match the missing products back to rows in your file and the offending column is normally obvious.

Separating ingestion errors from policy rejections

Not every missing product is a validation failure. Meta also runs commerce policy review over ingested items, and a product rejected on policy grounds (prohibited category, restricted content) disappears from active surfaces even though its row validated cleanly. The distinction matters because the fixes differ completely: validation failures are fixed in the feed file, policy rejections are appealed or resolved by changing the product or its landing page. The ingestion report timestamps and counts are your separator — a product that never ingested is a feed problem; a product that ingested and was later rejected is a policy problem. Diagnose from the data source report first, before assuming either.

Rebuilding the feed cleanly

Emit only the columns you maintain

The durable fix is a lean column set: required fields, the optional fields you actively populate and maintain, and nothing else. Every column in the file is a validation surface — a column you do not maintain is a rejection waiting for its first malformed value. Rebuild the export so that applink (and any other inherited column family) is emitted only when deliberately mapped from real data. Meta’s default ingestion format is a UTF-8 CSV with a header row and one product per line; keep the header exactly aligned with the columns you emit, because a header that names a column obligates every row beneath it to validate against that column’s rules. Fewer columns, fewer ways to fail.

Re-upload and verify the fix landed

After regenerating the file, trigger a fetch from the data source (or wait for the schedule) and verify rather than assume: the first fetch typically completes within about 15 minutes, after which the ingestion report should show zero invalid-field issues and a product count equal to your source row count. That count equality is the actual definition of fixed — an error message disappearing while ten rows still fail to ingest means a second trigger is hiding behind the first. If the count still falls short, repeat the diagnosis on the remaining shortfall; multiple inherited column families failing at once is common in migrated feeds, and each removal surfaces the next one.

Preventing the next rejection at build time

Validate before Meta does

Every rejection in this guide is detectable before upload: URL well-formedness, enum membership, required-companion rules like Android’s package requirement are all checkable mechanically against the published spec. That is feed validation as a build step — run the same checks Meta will run, fail the build instead of the row, and the ingestion report stays boring. The broader discipline of feed management treats the whole pipeline this way: one canonical catalog in, per-channel validated feeds out, with the channel’s current specification enforced at generation time rather than discovered at rejection time. Feeds that are validated at build time do not need heroic diagnosis after upload.

How FeedArc handles the applink class

FeedArc’s Meta Catalog export takes the lean-column position by default: applink columns are never emitted unless you explicitly map them, so the inherited-template rejection class cannot originate from a FeedArc feed. Before anything reaches Commerce Manager, the live CSV preview runs row-level validation — missing required fields, title overruns against Meta’s 200-character limit, broken image URLs, invalid availability values — so the errors this guide diagnoses are surfaced at build time, per row, while they are still one click from fixed. The same catalog that feeds Meta drives your other channels with per-channel transformations, which is what keeps a fix made once from regressing in the next export.

Limitations
  • Build-time validation covers what a spec defines mechanically. It cannot pre-verify judgements Meta makes after ingestion — policy review outcomes and image-quality assessments still happen on Meta’s side.

Meta versus Google: two rejection models

Row rejection versus item disapproval

It helps to place Meta’s behaviour next to the channel most merchants know best. Google Merchant Center ingests almost everything and then disapproves items individually, each with a named issue and a review workflow — the product exists in the account, visibly broken. Meta rejects at the gate: an invalid row never becomes a catalog item at all, and the evidence lives in the data source’s ingestion report rather than on a per-product diagnostics page. Neither model is stricter overall; they fail at different stages. The operational consequence is where you look first when products go missing — the Diagnostics page on Google, the ingestion counts on Meta — and this difference is exactly why the two channels need separate troubleshooting playbooks.

One catalog, per-channel correctness

The deeper lesson generalises: each channel enforces its own specification, and the same product data can be valid on one and rejected on another. Meta wants in stock where Google Shopping’s XML wants its own vocabulary; Meta embeds the currency in the price string where other formats separate it; Meta’s applink family exists nowhere else. Maintaining a separate hand-edited file per channel multiplies both the work and the failure surface. The scalable shape is a single source catalog with per-channel transformation and validation applied at export — every channel gets a feed shaped to its own rules, and a fix made in the catalog propagates to all of them on the next regeneration.

See FeedArc on your own feed

FeedArc runs Meta’s row-level checks before Commerce Manager ever sees your feed — a live per-row preview flags missing required fields, invalid availability values, and broken URLs at build time, and applink columns are never emitted unless you explicitly map them.

Create free accountFree to start · no credit card

Frequently asked questions

Sources & References

Start with FeedArc

Apply this playbook to your own product feed in minutes. Free to start, no credit card needed.