apache/seatunnel · error · IOException
Airtable API request failed, status code:[%s], content:[%s]
Error message
Airtable API request failed, status code:[%s], content:[%s]
What it means
AirtableSinkWriter.sendWithRateLimitRetry throws this IOException when the Airtable HTTP API returns a non-success, non-rate-limit status code. The message embeds the HTTP status and response body so you can see exactly why Airtable rejected the request (auth, bad table id, invalid payload, etc.).
Source
Thrown at seatunnel-connectors-v2/connector-http/connector-http-airtable/src/main/java/org/apache/seatunnel/connectors/seatunnel/airtable/sink/AirtableSinkWriter.java:151
}
if (response.getCode() == STATUS_TOO_MANY_REQUESTS
&& retryCount < rateLimitMaxRetries) {
retryCount++;
long backoffMillis = calculateBackoffMillis(retryCount);
log.warn(
"Airtable API rate limit reached, retry {}/{} after {} ms",
retryCount,
rateLimitMaxRetries,
backoffMillis);
try {
Thread.sleep(backoffMillis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
continue;
}
throw new IOException(
String.format(
"Airtable API request failed, status code:[%s], content:[%s]",
response.getCode(), response.getContent()));
} catch (IOException e) {
throw e;
} catch (Exception e) {
throw new IOException("Failed to send Airtable API request", e);
}
}
}
private void waitForRequestSlot() {
if (requestIntervalMs <= 0) {
return;
}
long now = System.currentTimeMillis();
long elapsed = now - lastRequestTimeMillis;
if (elapsed < requestIntervalMs) {View on GitHub (pinned to cf67b549a7)
Solutions
- Read the status code and content in the message: 401/403 → fix the Airtable API token and its scopes; 404 → correct baseId/tableId.
- For 422, align the SeaTunnel row fields/types with the Airtable table columns.
- Retry after transient 5xx; check https://status.airtable.com for outages.
- Increase or respect rate limiting so requests aren't rejected.
Example fix
// before: sink config with bad table id baseId = appXXXXXXXXXXXX tableId = WrongTable // after baseId = appXXXXXXXXXXXX tableId = tblRealTableId (copied from Airtable API docs URL)
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check before running the job
curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $AIRTABLE_TOKEN" "https://api.airtable.com/v0/$BASE_ID/$TABLE_ID?maxRecords=1" # expect 200 Try / catch
try { sinkWriter.prepareCommit(); } catch (RuntimeException e) { /* inspect cause IOException message for status code/content */ } Prevention
- Validate token and scopes with a test API call
- Copy baseId/tableId directly from the Airtable API URL
- Match row fields to the table schema
- Monitor https://status.airtable.com
When it happens
Trigger: Any Airtable API response with an error status that was not retried as 429: e.g. 401 invalid token, 403 forbidden, 404 unknown base/table, 422 invalid field value in the record payload.
Common situations: Expired or wrong personal access token, typo'd baseId/tableId in sink config, writing a record whose fields don't match the Airtable table schema, or Airtable-side outages returning 5xx.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Firebase HTTP request failed with status code %d. Response b
- REQUEST_FAILED
- Failed to send Airtable API request
- Failed to fetch metadata from Gravitino for metadata: %s
- fail get tableSchema:
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/f3c8ae905635c64a.
Report an issue: GitHub.