Skip to content

How to handle errors and failed posts ​

Errors come in two places. A request can be rejected up front (HTTP 4xx), or it can be accepted and then fail on one platform later. The first shows up as an exception from the SDK. The second shows up in the post's per-channel result.error. Handle both.

The error envelope and every message are listed in the error reference.

What kinds of failure are there? ​

CategoryExamplesWhat to do
Your requestBad slug, missing text, past scheduledAtFix the request. Do not retry.
Plan or guardrailUpload limit, X allowance, daily key limitWait, raise the limit or upgrade.
Auth on a platformreconnect_requiredRefresh or reconnect, then retry.
Platform issueRate limit, 5xxRetry later.
NetworkTimeout, DNSThe TypeScript SDK retries safe GET requests for you.

How do I catch typed errors in the TypeScript SDK? ​

typescript
import {
  SocifyrError, AuthenticationError, PermissionError, ValidationError,
  RateLimitError, UsageLimitError, NotFoundError,
} from '@socifyr/sdk'

try {
  await socifyr.uploads.text({ connections: ['x-myhandle'], text: 'Hello' })
} catch (err) {
  if (err instanceof ValidationError) {
    console.error('Fix the request:', err.message, err.errors)
  } else if (err instanceof RateLimitError) {
    await new Promise((r) => setTimeout(r, err.retryAfter * 1000))
  } else if (err instanceof UsageLimitError || err instanceof PermissionError) {
    console.error('Plan, permission or guardrail block:', err.message)
  } else if (err instanceof AuthenticationError) {
    console.error('Check SOCIFYR_API_KEY')
  } else if (err instanceof SocifyrError) {
    console.error(err.status, err.code, err.message)
  } else {
    throw err
  }
}

Match on err.message when you need a specific case, because plan blocks and guardrail blocks both arrive as 403. See SDK errors and, for Python, Python SDK errors.

How do I handle a post that was accepted but failed? ​

typescript
const upload = await socifyr.uploads.text(params)
const result = await socifyr.uploads.waitForCompletion(upload.id!)

if (result.status === 'partial_failure' || result.status === 'failed') {
  for (const ch of result.channels) {
    if (ch.result?.status !== 'failed') continue
    const error = ch.result.error ?? ''
    if (error.startsWith('reconnect_required')) {
      await socifyr.workspaces.refreshConnection(workspaceId, slugFor(ch))
    }
  }
  await socifyr.uploads.retry(upload.id!)
}

slugFor is your own lookup from ch.connectionId to a slug, using listConnections.

When should I retry? ​

Error text containsRetry?
rate limit, 429, daily limitYes, after the window resets.
timeout, network, temporarily, a 5xx codeYes, after a few minutes.
reconnect_requiredOnly after refresh or reconnect.
permission, scope, 403No. Reconnect and grant permissions first.
duplicateNo. Change the content.
aspect ratio, duration, file size, caption too longNo. Fix the media or text.
Connection "..." not found or not activeNo. Fix the slug.

How do I get notified instead of polling? ​

Subscribe a webhook to platform.failed and upload.partial_failure. See Webhooks. The payloads are in webhook payloads.

typescript
// inside your verified webhook handler
if (event.event === 'platform.failed') {
  await queueRetry(event.payload.uploadId, { delayMinutes: 10 })
}

What should I log? ​

Log the post ID and per-channel results. Never log the API key.

typescript
logger.info({
  uploadId: upload.id,
  status: result.status,
  channels: result.channels.map((c) => ({
    platform: c.platform,
    status: c.result?.status,
    error: c.result?.error,
  })),
})

FAQ ​

Does the SDK retry failed requests? ​

Only GET, HEAD and OPTIONS are retried automatically. Writes are not, so retry them yourself and use an idempotencyKey to avoid duplicates.

Where do I find the exact error messages? ​

In the error reference.

Next steps ​