Common publishing errors explained

Last updated: May 19, 2026

Common publishing errors explained

Wevion validates campaigns via apps/backend/src/services/launch-validation.service.ts (verified). Errors surface as ValidationIssue objects with code, fieldPath, message, metaErrorCode, severity. Pre-flight (POST /api/v1/campaign-drafts/:id/preflight) catches most issues before publish. Field-level validation (POST /:id/validate-field) on blur catches earlier.

Who is this for

Mediabuyers hitting validation errors in Express, Pro, or Bulk Launch. Anyone wondering "what does INVALID_AGE_RANGE actually mean".

ValidationIssue structure

Verified apps/backend/src/types/campaigns/validation.types.ts:

interface ValidationIssue {
  code: string             // e.g. "INVALID_AGE_RANGE"
  fieldPath: string        // e.g. "adSets[0].targeting.ageMin"
  message: string          // human-friendly description
  metaErrorCode?: number   // Meta API error code if from Meta side
  severity: 'error' | 'warning' | 'info'
}

Errors block publish; warnings allow but flag concerns; info is informational.

Top 10 errors

1. INVALID_AGE_RANGE

fieldPath: adSets[N].targeting.ageMin or ageMax

Cause: age range out of acceptable bounds — typically ageMin < 13 (Meta minimum) OR ageMax > 65 (Meta upper bound, unless 65+).

Fix: set age range 13-65 (or 13-65+) per Meta minimum age policy. Some categories require 18+ (CREDIT/EMPLOYMENT/HOUSING — see cc-120).

2. MISSING_PIXEL

fieldPath: ads[N].conversionPixelId

Cause: campaign objective is conversion-based (Sales / Leads) but no pixel selected.

Fix: pick a pixel from the dropdown OR set up new pixel in Meta Events Manager. See meta-105 pixels and CAPI.

3. AUDIENCE_TOO_NARROW

fieldPath: adSets[N].targeting

Cause: estimated audience reach < 1.000 (platform-side minimum for delivery).

Fix: broaden audience — add countries, expand age range, remove interest layers, or use lookalike instead of narrow custom audience.

4. DSA_BENEFICIARY_REQUIRED

fieldPath: campaign.dsaBeneficiary

Cause: targeting includes EU country but DSA dsa_beneficiary field empty.

Fix: enter the legal entity benefiting from the ad (your company's legal name, or client's for agency). See cc-120 EU compliance.

5. BUDGET_BELOW_MINIMUM

fieldPath: campaign.dailyBudget or adSets[N].dailyBudget

Cause: budget below platform's minimum:

  • Meta: ~$1/day daily (currency-converted)

  • Google: ~$1/day

  • TikTok: ~$5/day for some objectives

  • Snapchat: ~$5/day

Fix: increase budget OR switch to lifetime budget with proportional duration.

6. INVALID_CTA_FOR_OBJECTIVE

fieldPath: ads[N].cta

Cause: CTA doesn't match objective (e.g. SHOP_NOW with Awareness objective).

Fix: pick CTA aligned with objective. For Sales/Leads: SHOP_NOW, SIGN_UP, BOOK_NOW. For Awareness/Traffic: LEARN_MORE, WATCH_VIDEO. See cc-115 ad copy.

7. CREATIVE_SPEC_MISMATCH

fieldPath: ads[N].creative

Cause: creative doesn't meet platform's spec (wrong aspect ratio, file too large, unsupported format).

Fix:

  • For aspect: re-crop or re-upload native ratio (1:1, 9:16, 16:9 per placement)

  • For file size: compress or split

  • For format: convert to JPG/PNG/WebP for images; MP4/MOV for video

  • See cc-113 images, cc-114 videos

8. DUPLICATE_AD_NAME

fieldPath: ads[N].name

Cause: two ads in the same campaign have the same name. Platforms require unique names.

Fix: rename one. Use versioning suffix (e.g. Ad Name v1, Ad Name v2).

9. MISSING_DESTINATION_URL

fieldPath: ads[N].destinationUrl

Cause: campaign objective requires a destination (Traffic / Sales / Leads / App) but URL field empty.

Fix: enter a valid HTTPS URL. URL must:

  • Be reachable (no 404)

  • Have HTTPS (HTTP rejected by most platforms)

  • Match your domain (if domain verification required by Meta for iOS 14.5+ — see meta-105)

10. SPECIAL_AD_CATEGORY_VIOLATION

fieldPath: campaign.specialAdCategory or adSets[N].targeting

Cause: special ad category set (CREDIT/EMPLOYMENT/HOUSING/SOCIAL_ISSUES) but targeting includes restricted dimensions (narrow age, ZIP for housing, certain interests).

Fix: remove the restricted targeting:

  • For HOUSING: no ZIP code targeting allowed

  • For all special categories: full age range 18-65+, gender = All

  • For SOCIAL_ISSUES_ELECTIONS_OR_POLITICS: complete authorized advertiser verification with Meta first

See cc-120 EU compliance + special categories.

Other common errors

Code

Cause

Fix

MISSING_PAGE

Meta campaign needs Page selected for ad source

Pick Page from dropdown (see meta-104)

INVALID_BIDDING_STRATEGY

Bid strategy incompatible with optimization goal

Pick compatible bid strategy (see cc-107 budget CBO vs ABO)

OBJECTIVE_NOT_SUPPORTED_FOR_PLATFORM

Selected objective doesn't exist on the chosen platform

Pick platform-supported objective (cc-106)

INVALID_CONVERSION_EVENT

Conversion event selected but pixel doesn't report it

Verify pixel events at /pixels OR pick reported event

BUDGET_OPTIMIZATION_REQUIRES_BID_AMOUNTS

ABO with COST_CAP needs per-adset bid_amount

Provide bid_amount per ad set in Pro mode or Bulk Launch

MISSING_LANDING_PAGE_VIEW

Optimization goal LANDING_PAGE_VIEWS needs pixel

Pick pixel; ensure PageView event firing

IMAGE_TEXT_EXCEEDS_LIMIT

Legacy Meta 20% text rule (deprecated 2021 but still surfaces sometimes)

Reduce text on creative or ignore the warning

INVALID_URL_FORMAT

URL has formatting issues

Verify HTTPS + valid format; no extra spaces/quotes

META_ERROR_FOO_BAR

Generic Meta API error pass-through (metaErrorCode populated)

Look up Meta error code in Meta Marketing API docs

How validation runs

Field-level (real-time)

POST /api/v1/campaign-drafts/:id/validate-field triggers on blur of each field. Inline error shown immediately. Surfaces issues like INVALID_AGE_RANGE, BUDGET_BELOW_MINIMUM as you type.

Pre-flight (before publish)

POST /api/v1/campaign-drafts/:id/preflight runs comprehensive validation. Returns ValidationResult:

{
  errors: ValidationIssue[],    // block publish
  warnings: ValidationIssue[],  // allow with confirm
  info: ValidationIssue[],      // informational
  valid: boolean                // overall pass/fail
}

If errors > 0: publish blocked. Modal shows full list with fix suggestions.

Dry-run (simulate without publishing)

POST /api/v1/campaign-drafts/:id/dry-run simulates publish via launch provider's dry_run mode. Returns what would happen without actually creating campaigns. Useful for last-mile verification.

Bulk Launch validation

Per-row + cross-row validation:

  • Per row: same rules as single campaign

  • Cross-row: duplicate campaign names within an account, conflicting bid amounts on same account, inconsistent UTM patterns

Failed rows surface in red on the grid; click row for full error detail. Fix individual rows + retry just those.

Validation severity

Severity

Behavior

error

Publish blocked; must fix before continuing

warning

Publish allowed; modal asks for explicit confirmation

info

Just FYI; no action required

Don't ignore warnings — they often catch suboptimal setups (audience too narrow but not blocked, creative spec might cut off, etc.).

What you'll see

In Express creative step:

  • Red field highlight + tooltip on error

  • Pre-flight summary at top of review step

In Pro mode:

  • Validation badge per node (campaign/adset/ad) in structure tree

  • Inline per-field errors

  • Top-bar "N errors, M warnings" summary

In Bulk Launch grid:

  • Per-cell red border on errors

  • Per-row red badge with error count

  • Bottom-bar "X rows, Y errors, Z warnings"

Best practices

Read the message, not just the code

Error message has the specific fix suggestion. Codes are just for tracking.

Use pre-flight before every publish

Even if no field-level errors during editing: run preflight. Catches cross-field issues.

For Bulk Launch: validate before publishing all

Toolbar "Validate all" runs full preflight on every row. Fix failures before clicking Publish all.

Build templates with known-good config

Campaign templates saved from successfully-published campaigns avoid the most-common errors automatically.

Related