signalapp/Signal-Server · error · IOException
Got a non-200 reply from source URI:
Error message
Got a non-200 reply from source URI:
What it means
CopyToS3Command only uploads when the source server returns HTTP 200. Any other status code (404, 403, 500, redirects, etc.) causes an IOException with this message, including the actual status code, because the command does not follow non-200 flows.
Solutions
- Verify the source URI with curl -I and confirm it returns 200
- Fix authentication or credentials if the source returns 401/403
- Correct the URI/path if it returns 404
- Ensure the server responds 200 rather than a redirect, or point at the final URL
Example fix
// before httpRequest to https://example.org/old-path // after httpRequest to https://example.org/new-path (verified 200 via curl -I)
Defensive patterns
Strategy: validation
Validate before calling
HttpRequest request = HttpRequest.newBuilder(URI.create(sourceUri)).build();
HttpResponse<Void> probe = httpClient.send(request, HttpResponse.BodyHandlers.discarding());
if (probe.statusCode() != 200) throw new IllegalStateException("source not 200: " + probe.statusCode()); Try / catch
try { copyToS3(...); } catch (IOException e) { logger.error("non-200 from {}: {}", sourceUri, e.getMessage()); } Prevention
- Verify the URI returns 200 with curl -I first
- Point at the final URL, not a redirect
- Confirm auth/credentials for protected sources
When it happens
Trigger: Running `copy-to-s3` against a URI that responds with any status other than 200 — the httpClient.send() completes but the else-branch throws.
Common situations: Typo in the source URI path; missing auth so the origin replies 403; server moved the file (404); source replying 301/302 redirect that isn't followed; upstream 5xx during maintenance.
Related errors
- Response body was below minimum
- Registration service failure
- registration service unavailable
- 503 Service Unavailable
- Empty body not allowed
AI-assisted analysis of signalapp/Signal-Server@100ab61c82 (2026-09-09).
Data as JSON: /api/errors/27dbea760f75cecf.
Report an issue: GitHub.
Appendix: source
Thrown at service/src/main/java/org/whispersystems/textsecuregcm/workers/CopyToS3Command.java:113
.formatted(httpResponse.body().length, minimumExpectedSize));
}
final String contentType = httpResponse.headers().firstValue("Content-Type").orElse("application/octet-stream");
s3Client.putObject(PutObjectRequest.builder()
.bucket(s3Bucket)
.key(filename)
.contentType(contentType)
.contentLength((long) httpResponse.body().length)
.build(), RequestBody.fromBytes(httpResponse.body()));
logger.info("Copied {} bytes from {} to s3://{}/{}",
httpResponse.body().length,
httpRequest.uri(),
s3Bucket,
filename);
} else {
throw new IOException("Got a non-200 reply from source URI: " + httpResponse.statusCode());
}
}
}
}
View on GitHub (pinned to 100ab61c82)