#3

Opened by Seraiah on Sep 27, 2026, 2:52 AM
Approve the patches, then land them on main with:
// Seraiah on Sep 27, 2026, 2:52 AM

pijul-remote discards HTTP error bodies, hiding the server’s own explanation

On 1.0.0-beta.24, pushing to an HTTPS remote fails with only:

Error: HTTP error: 404 Not Found

The server is in fact returning a clear explanation, which the client throws away:

$ curl -s "https://nest.pijul.com/pijul/pijul/.pijul?apply=AAAA&channel=main"
Pushing over HTTP is not supported — push over SSH instead.

pijul-remote/src/http.rs returns RemoteError::HttpError(res.status()) at eight sites — lines 98, 393, 427, 472, 524, 564, 584, 626 — without ever reading the response body. So every HTTP failure surfaces as a bare status code even when the server has said exactly what went wrong.

This cost me a while: I read the 404 as a broken account or key setup and went looking in the wrong place. Including the body would have made it self-explanatory.

Same issue makes a second error opaque: pijul http-token returns HTTP error: 422 Unprocessable Entity, and whatever the server said about why is likewise discarded.

Environment: pijul 1.0.0-beta.24 via cargo install, macOS (Darwin 25.6, Apple Silicon), thrussh 0.49.0.

Unrelated but noticed nearby: the README still references ssh.pijul.com, which is NXDOMAIN on both 8.8.8.8 and 1.1.1.1.

  • AI Generated
// berkus on Sep 27, 2026, 11:07 AM

Thank you!

// berkus on Sep 27, 2026, 11:08 AM

If the server already generates the response, should this be applied to pijul client in fact?

// Seraiah on Sep 29, 2026, 12:47 AM

I think it has to stay in pijul-remote.

RemoteError carries a variant for this:

#[error("HTTP error: {0}")]
HttpError(reqwest::StatusCode),

#[error("HTTP server returned an error: {0}")]
HttpServerError(String),

one call site in http.rs already uses it, around line 284:

let body = resp.text().await?;
if !body.is_empty() {
    return Err(RemoteError::HttpServerError(body));
} else {
    return Err(RemoteError::HttpError(stat));
}

The pattern is already established in the same file. The eight sites I listed just return HttpError(res.status()) without reading the body first.

I don’t think it can move to the client: by the time the error surfaces there, the body is gone. pijul-remote is the only place still holding the reqwest::Response, and returning just the status drops it. The text the user sees comes from the #[error(…)] attribute on the enum, so the client needs no change at all — switching those eight sites to HttpServerError(body) would make the server’s message appear on its own.

That would also cover the http-token 422, since it goes through the same path. AIG