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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Feed validation is the process of checking a product feed against a channel's schema and rules — required fields, data types, value formats, and business logic — before upload, so errors are caught locally rather than after disapproval.
A product feed is a structured file (XML, CSV, TSV, or JSON) that lists every product in your catalog with the fields advertising and marketplace platforms need to display them.
Feed management is the process of collecting product data from an e-commerce store, validating and enriching it against per-channel specifications, and distributing the resulting feeds to advertising channels and marketplaces so the products can be sold across them.
Apply this playbook to your own product feed in minutes. Free to start, no credit card needed.