apache/seatunnel · error · SeaTunnelException

timeout_ms must be greater than 0

Error message

timeout_ms must be greater than 0

What it means

FirebaseHttpClient's constructor validates the timeout_ms config and throws SeaTunnelException if it is zero or negative. The HTTP client requires a positive connect/read timeout in milliseconds. This fails fast at source initialization rather than producing hangs later.

Source

Thrown at seatunnel-connectors-v2/connector-firebase/src/main/java/org/apache/seatunnel/connectors/seatunnel/firebase/client/FirebaseHttpClient.java:73

    private static final int MAX_ERROR_BODY_BYTES = 4096;
    private final String baseUrl;
    private final String path;
    private final int timeoutMs;
    private final Map<String, String> extraQueryParams;
    private static final List<String> FIREBASE_SCOPES =
            Arrays.asList(
                    "https://www.googleapis.com/auth/firebase.database",
                    "https://www.googleapis.com/auth/userinfo.email");
    private final GoogleCredentials credentials;
    private final String databaseSecret;
    private final ReentrantLock tokenLock = new ReentrantLock();

    public FirebaseHttpClient(ReadonlyConfig config) {
        this.baseUrl = config.get(FirebaseSourceOptions.URL).replaceAll("/+$", "");
        this.path = config.get(FirebaseSourceOptions.PATH).replaceAll("^/+|/+$", "");
        int toms = config.get(FirebaseSourceOptions.TIMEOUT_MS);
        if (toms <= 0) {
            throw new SeaTunnelException("timeout_ms must be greater than 0");
        }
        this.timeoutMs = toms;
        this.extraQueryParams =
                config.getOptional(FirebaseSourceOptions.QUERY_PARAMS)
                        .orElse(Collections.emptyMap());

        this.credentials = initGoogleCredentials(config);
        this.databaseSecret =
                config.getOptional(FirebaseSourceOptions.DATABASE_SECRET).orElse(null);
        if (this.credentials != null) {
            log.info("Initialized FirebaseHttpClient with Google OAuth2 Service Account.");
        } else if (StringUtils.isNotEmpty(this.databaseSecret)) {
            log.info("Initialized FirebaseHttpClient with Legacy Database Secret.");
        } else {
            log.info("Initialized FirebaseHttpClient without authentication (Public Read).");
        }
    }

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Set timeout_ms to a positive integer, e.g. timeout_ms = 30000.
  2. Remove the timeout_ms option entirely if a default is acceptable (check the option's default).
  3. Verify the config value is not inherited/overridden to 0 by a higher-priority config source.

Example fix

// before
Firebase {
  url = "https://mydb.firebaseio.com"
  path = "/users"
  timeout_ms = 0
}
// after
Firebase {
  url = "https://mydb.firebaseio.com"
  path = "/users"
  timeout_ms = 30000
}
Defensive patterns

Strategy: validation

Validate before calling

int toms = config.get(FirebaseSourceOptions.TIMEOUT_MS);
if (toms <= 0) throw new IllegalArgumentException("timeout_ms must be > 0, got: " + toms);

Prevention

When it happens

Trigger: Configuring timeout_ms = 0 or a negative value in the Firebase source options; omitting a valid positive integer and passing an invalid literal that resolves to <= 0 via config coercion.

Common situations: Users copying example configs with timeout_ms = 0 thinking it means 'no timeout' (in some libraries 0 means infinite, here it is rejected); typos like timeout_ms = -1.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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