PostPost

Validation

This guide covers how PostPost validates posts before scheduling to prevent publish failures, including what gets validated, the validation response format, error codes, and best practices for avoiding validation errors.

Overview

Posts are validated before scheduling to catch issues that would cause publishing failures on target platforms. Each social media platform has unique requirements for content length, media types, file sizes, and video durations. PostPost validates your posts against these platform-specific limits and returns detailed error information so you can fix issues before scheduling.

Validation runs when you change a post's status to scheduled in the PostPost dashboard. The REST API create-post endpoint does not trigger full validation -- it only performs basic field presence checks. See the "When Validation Occurs" section below for details.

When Validation Occurs

Validation runs automatically on these API calls:

EndpointTrigger
Dashboard update to scheduled statusWhen changing a post's status to scheduled in the dashboard

Note: The POST /api/v1/create-post API endpoint does not run post validation (postValidationService.validatePostGroup). It only performs basic field presence checks (content, platforms, scheduledTime format). Full validation only runs in the dashboard flow when updating a post to scheduled status. The PUT /api/v1/update-post/:id endpoint also does not invoke the validation service -- it only accepts status and scheduledTime fields (for rescheduling or changing draft/scheduled status).

If validation fails with blocking errors, the API returns a 400 status code with details about what needs to be fixed. Warnings are returned but do not block the operation.

What Gets Validated

Content Length

Each platform has a maximum character limit. Some platforms also have minimum requirements.

PlatformMax CharactersNotes
Twitter/X280 (standard) / 25,000 (Premium)Threading supported for long content
Instagram2,200First 125 chars visible before "more"
Threads500 (10,000 with text attachment)Max 5 links per post
TikTok2,200 (API)Native app allows 4,000
LinkedIn3,000First 210 chars visible before "see more"
YouTube100 (title) / 5,000 (description)First 150 chars of description visible
Facebook63,206Posts under 80 chars get higher engagement
Mastodon500Instance-configurable (some allow 5,000+)
Bluesky300Links count toward the limit in PostPost
Telegram4,096 (users) / 1,024 (bot captions)Bots limited to 1,024 for captions
Pinterest100 (title) / 800 (description)Optimal description: 220-232 chars. Pinterest is in the platform registry but publishing support is not yet fully available/tested.

Media Requirements

Some platforms require media, while others support text-only posts.

PlatformRequires MediaRequires VideoSupports Text-Only
Twitter/XNoNoYes
InstagramYesNoNo
ThreadsNoNoYes
TikTokYesYesNo
LinkedInNoNoYes
YouTubeYesYesNo
FacebookNoNoYes
MastodonNoNoYes
BlueskyNoNoYes
TelegramNoNoYes
PinterestYesNoNo

Media File Sizes

PlatformMax Image SizeMax Video SizeMax Media Count
Twitter/X5 MB512 MB4 images OR 1 video
Instagram8 MB300 MB10 (API carousel)
Threads8 MB500 MB10
TikTok-4 GB1 video only
LinkedIn5 MB500 MB10 images OR 1 video
YouTube-256 GB1 video only
Facebook10 MB2 GB (API)10 images OR 1 video
Mastodon16 MB~99 MB4
Bluesky1 MB100 MB4
Telegram10 MB50 MB (Bot API)10
Pinterest20 MB1 GB5 (carousel)

Media Formats

PlatformSupported Image FormatsSupported Video Formats
Twitter/XJPEG, PNG, GIF, WebPMP4, MOV
InstagramJPEG only (API)MP4, MOV
ThreadsJPEG, PNGMP4, MOV
TikTok-MP4, MOV, WebM
LinkedInJPEG, PNG, GIFMP4
YouTube-MP4, MOV, AVI, WebM
FacebookJPEG, PNG, GIF, BMP, TIFFMP4, MOV
MastodonJPEG, PNG, GIF, WebPMP4, MOV, WebM
BlueskyJPEG, PNG, WebP (max 2000x2000 px)MP4
TelegramJPEG, PNG, GIF, WebP, BMPMP4, MOV, AVI, MKV, WebM
PinterestJPEG, PNG, TIFF, BMP, GIF, WebPMP4, MOV

Critical: Instagram API only accepts JPEG images. PNG and GIF will fail validation.

Video Duration Limits

PlatformMin DurationMax Duration (API)Notes
Twitter/X-2 min (120s)Native allows 2:20
Instagram Reels-3 min (180s)Native allows 15-20 min
Instagram Carousel-60s per video-
Threads-5 min-
TikTok3 seconds10 minNative allows 60 min
LinkedIn-30 min-
YouTube-12 hours-
Facebook-45 minNative allows 240 min
Facebook Reels3 seconds90 seconds-
Mastodon-No limit**Limited by file size
Bluesky-3 minDaily limit: 25 videos OR 10 GB
Telegram-No limitLimited by 50 MB file size
Pinterest-15 min-

Validation Response Format

Note: The structured validation response below (with validation.errors[], validation.warnings[], and validation.summary) is returned by the dashboard validation endpoint only. The REST API create-post endpoint does not run the full validation service and will not return this format (it only performs basic field presence checks). The REST API update-post endpoint and MCP update_post tool also do not invoke the validator.

When validation errors occur, the API returns a 400 status code with a structured response:

{
  "error": "Validation failed",
  "validation": {
    "valid": false,
    "errors": [
      {
        "platform": "instagram",
        "code": "MEDIA_REQUIRED",
        "message": "Instagram posts require media",
        "field": "media",
        "severity": "error"
      },
      {
        "platform": "tiktok",
        "code": "VIDEO_REQUIRED",
        "message": "TikTok posts require a video",
        "field": "video",
        "severity": "error"
      }
    ],
    "warnings": [
      {
        "platform": "twitter",
        "code": "CONTENT_TOO_LONG",
        "message": "Content exceeds Twitter/X's 280 character limit (currently 450)",
        "field": "content",
        "severity": "warning",
        "constraint": "maxLength",
        "currentValue": 450
      }
    ],
    "summary": {
      "affectedPlatforms": ["instagram", "tiktok", "twitter"],
      "errorCount": 2,
      "warningCount": 1
    }
  }
}

Response Fields

FieldTypeDescription
validbooleantrue if all platforms pass validation, false otherwise
errorsarrayBlocking errors that must be fixed before scheduling
warningsarrayNon-blocking issues that may affect publishing
summary.affectedPlatformsarrayList of platform names with errors or warnings
summary.errorCountnumberTotal number of errors
summary.warningCountnumberTotal number of warnings

Error/Warning Object Fields

FieldTypeDescription
platformstringPlatform name (e.g., "twitter", "instagram")
codestringMachine-readable error code
messagestringHuman-readable error description
fieldstringThe field that caused the error (e.g., "content", "imageSize", "videoSize", "imageFormat", "videoDuration", "video", "settings")
severitystringEither "error" (blocking) or "warning" (non-blocking)
constraintstring(optional) String descriptor of the violated constraint (e.g., "maxLength", "maxCount", "maxSize", "maxDuration", "requiredType")
currentValuenumber/string(optional) The current value that exceeded the constraint
maxValuenumber/string(optional) The maximum allowed value
minValuenumber/string(optional) The minimum required value
suggestionsstring[](optional) Suggested fixes or alternative actions

Error Codes Reference

Content Errors

CodeDescriptionResolution
CONTENT_TOO_LONGContent exceeds the platform's character limitShorten the content or use threading where supported. Note: On threading-capable platforms (Twitter, Threads) with threading enabled, this is a warning (content will be auto-threaded). On other platforms or when threading is disabled, it is an error.
CONTENT_TOO_SHORTContent is below the minimum required lengthAdd more content

Reserved -- not currently emitted by the validation service.

| CONTENT_REQUIRED | Text content is required but missing | Add text content to the post |

Reserved -- not currently emitted by the validation service. | CONTENT_OR_MEDIA_REQUIRED | Either text or media is needed | Add content or attach media | | THREAD_PART_TOO_LONG | A single thread part exceeds the platform's per-part character limit | Break the thread part into smaller segments. (This code is defined in the @postpost/platform-limits package. Threading validation may occur in a separate service.) | | INVALID_PLATFORM_CONTENT | Content contains elements not supported by the platform | Remove unsupported content elements. (This error code is defined in the codebase but not currently emitted by the validation service.) |

Media Errors

CodeDescriptionResolution
MEDIA_REQUIREDPlatform requires at least one media fileAttach an image or video
MEDIA_SIZE_EXCEEDEDFile exceeds the platform's size limitCompress or resize the file
MEDIA_COUNT_EXCEEDEDToo many media files attachedReduce the number of files
MEDIA_TYPE_NOT_SUPPORTEDFile format not supported by the platformConvert to a supported format
MEDIA_DIMENSIONS_INVALIDImage dimensions outside allowed rangeResize the image
IMAGES_NOT_SUPPORTEDPlatform is video-only (TikTok, YouTube)Use a video instead

Reserved -- not currently emitted by the validation service.

Video Errors

CodeDescriptionResolution
VIDEO_REQUIREDPlatform requires a video (TikTok, YouTube)Attach a video file
VIDEO_DURATION_EXCEEDEDVideo is longer than the platform allowsTrim the video to meet the limit
VIDEO_DURATION_TOO_SHORTVideo is shorter than the minimum requiredUse a longer video (min 3s for TikTok/FB Reels)
VIDEO_NOT_SUPPORTEDPlatform does not support videoRemove the video or change target platforms

Reserved -- not currently emitted by the validation service.

Platform Errors

CodeDescriptionResolution
PLATFORM_NOT_SUPPORTEDUnknown or unsupported platformCheck the platform ID format
PLATFORM_SETTING_REQUIREDA required platform-specific setting is missingProvide the required setting
PLATFORM_SETTING_INVALIDA platform-specific setting has an invalid valueCorrect the setting value

System Errors

CodeDescriptionResolution
VALIDATION_SYSTEM_ERRORAn internal error occurred during validationRetry the request; if persistent, contact support

Examples

Validation Error: Missing Media for Instagram

When posting to Instagram without media:

Request:

{
  "content": "Check out our latest update!",
  "platforms": ["twitter-123", "instagram-456"]
}

Response (400):

{
  "error": "Validation failed",
  "validation": {
    "valid": false,
    "errors": [
      {
        "platform": "instagram",
        "code": "MEDIA_REQUIRED",
        "message": "Instagram posts require media",
        "field": "media",
        "severity": "error"
      }
    ],
    "warnings": [],
    "summary": {
      "affectedPlatforms": ["instagram"],
      "errorCount": 1,
      "warningCount": 0
    }
  }
}

Validation Error: Video Required for TikTok

When posting an image to TikTok (video-only platform):

Request:

{
  "content": "New product announcement!",
  "platforms": ["tiktok-789"],
  "media": [{ "type": "image", "url": "https://..." }]
}

Response (400):

{
  "error": "Validation failed",
  "validation": {
    "valid": false,
    "errors": [
      {
        "platform": "tiktok",
        "code": "VIDEO_REQUIRED",
        "message": "TikTok posts require a video",
        "field": "video",
        "severity": "error"
      }
    ],
    "warnings": [],
    "summary": {
      "affectedPlatforms": ["tiktok"],
      "errorCount": 1,
      "warningCount": 0
    }
  }
}

Validation Error: Content Too Long

When content exceeds Twitter's 280 character limit:

Threading note: This example shows CONTENT_TOO_LONG as an "error" with severity: "error". However, on threading-capable platforms (Twitter/X, Threads) with threading enabled, this would be a warning (severity: "warning") instead, because the content will be automatically split into a thread. The example below assumes threading is disabled.

Response (400):

{
  "error": "Validation failed",
  "validation": {
    "valid": false,
    "errors": [
      {
        "platform": "twitter",
        "code": "CONTENT_TOO_LONG",
        "message": "Content exceeds Twitter/X's 280 character limit (currently 450)",
        "field": "content",
        "severity": "error"
      }
    ],
    "warnings": [],
    "summary": {
      "affectedPlatforms": ["twitter"],
      "errorCount": 1,
      "warningCount": 0
    }
  }
}

Validation Error: Image Format Not Supported

When uploading a PNG to Instagram (JPEG only via API):

Response (400):

{
  "error": "Validation failed",
  "validation": {
    "valid": false,
    "errors": [
      {
        "platform": "instagram",
        "code": "MEDIA_TYPE_NOT_SUPPORTED",
        "message": "Image format \"image/png\" is not supported on Instagram",
        "field": "imageFormat",
        "severity": "error"
      }
    ],
    "warnings": [],
    "summary": {
      "affectedPlatforms": ["instagram"],
      "errorCount": 1,
      "warningCount": 0
    }
  }
}

Validation Error: Video Duration Exceeded

When a video exceeds platform limits:

Response (400):

{
  "error": "Validation failed",
  "validation": {
    "valid": false,
    "errors": [
      {
        "platform": "instagram",
        "code": "VIDEO_DURATION_EXCEEDED",
        "message": "Video duration (3m 0s) exceeds Instagram's 60s carousel limit",
        "field": "videoDuration",
        "severity": "error"
      },
      {
        "platform": "twitter",
        "code": "VIDEO_DURATION_EXCEEDED",
        "message": "Video duration (3m 0s) exceeds Twitter/X's 2m 0s limit",
        "field": "videoDuration",
        "severity": "error"
      }
    ],
    "warnings": [],
    "summary": {
      "affectedPlatforms": ["instagram", "twitter"],
      "errorCount": 2,
      "warningCount": 0
    }
  }
}

Validation Error: File Size Exceeded

When an image exceeds Bluesky's strict 1 MB limit:

Response (400):

{
  "error": "Validation failed",
  "validation": {
    "valid": false,
    "errors": [
      {
        "platform": "bluesky",
        "code": "MEDIA_SIZE_EXCEEDED",
        "message": "Image (2.5MB) exceeds Bluesky's 1.0MB limit",
        "field": "imageSize",
        "severity": "error"
      }
    ],
    "warnings": [],
    "summary": {
      "affectedPlatforms": ["bluesky"],
      "errorCount": 1,
      "warningCount": 0
    }
  }
}

Multiple Platform Errors

When a single post has issues on multiple platforms:

Response (400):

{
  "error": "Validation failed",
  "validation": {
    "valid": false,
    "errors": [
      {
        "platform": "instagram",
        "code": "MEDIA_TYPE_NOT_SUPPORTED",
        "message": "Image format \"image/png\" is not supported on Instagram",
        "field": "imageFormat",
        "severity": "error"
      },
      {
        "platform": "bluesky",
        "code": "MEDIA_SIZE_EXCEEDED",
        "message": "Image (2.5MB) exceeds Bluesky's 1.0MB limit",
        "field": "imageSize",
        "severity": "error"
      },
      {
        "platform": "tiktok",
        "code": "VIDEO_REQUIRED",
        "message": "TikTok posts require a video",
        "field": "video",
        "severity": "error"
      }
    ],
    "warnings": [],
    "summary": {
      "affectedPlatforms": ["instagram", "bluesky", "tiktok"],
      "errorCount": 3,
      "warningCount": 0
    }
  }
}

Best Practices

  1. Validate content length client-side. Check character counts before sending the API request. Different platforms have different limits (Twitter: 280, LinkedIn: 3,000, Bluesky: 300).

  2. Always use JPEG for Instagram. The Instagram API does not support PNG or GIF. Convert images to JPEG before uploading.

  3. Compress images for Bluesky. Bluesky has a strict 1 MB limit. Use JPEG compression at 80-85% quality to stay under the limit.

  4. Check video durations before uploading. Instagram Reels API maxes out at 3 minutes (180s), carousel videos at 60 seconds, Twitter at 2 minutes, TikTok at 10 minutes. Trim videos accordingly.

  5. Use separate media for different platform groups. If posting to both image and video platforms, consider creating separate posts:

    • Image posts for Instagram, Twitter, LinkedIn
    • Video posts for TikTok, YouTube
  6. Handle validation errors gracefully in your UI. Display platform-specific error messages so users know exactly what to fix.

  7. Consider platform requirements when designing content. If targeting TikTok, always start with video. If targeting Instagram, prepare JPEG images.

  8. Keep Bluesky image dimensions under 2000x2000 pixels. Larger images will fail validation.

  9. For Telegram bots, keep captions under 1,024 characters. Bots cannot exceed this limit even though users can send 4,096 characters.

  10. Test video FPS for TikTok. TikTok has minimum FPS requirements. Videos with very low frame rates will fail at publish time.

Common Issues

ProblemCauseSolution
Instagram post fails with MEDIA_TYPE_NOT_SUPPORTEDUsing PNG or GIF formatConvert to JPEG before uploading
TikTok post fails with VIDEO_REQUIREDPosting images to a video-only platformUse a video file instead
Bluesky post fails with MEDIA_SIZE_EXCEEDEDImage over 1 MBCompress to 80-85% JPEG quality
Twitter post fails with CONTENT_TOO_LONGContent over 280 charactersShorten content or use threading
Instagram Reels fails with VIDEO_DURATION_EXCEEDEDVideo over 3 minutesTrim video to under 3 minutes (180s)
Multiple platforms fail with different errorsContent not optimized for all targetsCreate platform-specific posts or fix each error
Validation passes but publish failsPlatform-side issues (rate limits, account restrictions)Check platform-specific error messages in the post status

On this page