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

  1. Read the status code and content in the message: 401/403 → fix the Airtable API token and its scopes; 404 → correct baseId/tableId.
  2. For 422, align the SeaTunnel row fields/types with the Airtable table columns.
  3. Retry after transient 5xx; check https://status.airtable.com for outages.
  4. 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

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


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/f3c8ae905635c64a. Report an issue: GitHub.