From cb36f284a6c28235188b172b5e196de5dac0c59a Mon Sep 17 00:00:00 2001 From: AdaAibaby <8872412+adababys@users.noreply.github.com> Date: Fri, 23 Oct 2026 11:30:19 +0800 Subject: [PATCH] fix(orchestrator): raise envd error-body cap from 100 to 512 runes An envd call failure embeds the response body in the returned error and the init-failure log via envdErrorBody, capped at 100 runes. A volume-mount failure body carries the full chroot/bind path plus the errno text (~300 chars), so the 100-rune cut falls mid-path and strips the actual cause (no such file or directory, permission denied, ...), leaving an error that names a truncated path and nothing else. Raise envdErrorBodyRunes to 512 so the whole diagnostic survives. The body is still bounded: envdErrorBody reads through io.LimitReader(envdErrorBodyRunes* utf8.UTFMax+1) and Truncate still marks a longer body as cut, so the read-a-bounded-body protection is preserved - only the bound is larger. envd error bodies are short server-generated diagnostics, not arbitrary user data, so 512 carries no log-explosion risk. Rebased onto current main, which since the original attempt (#3481) refactored the four scattered utils.Truncate(string(body), 100) call sites into the single envdErrorBody helper; this changes only the cap constant. Existing tests updated to reference envdErrorBodyRunes instead of hard-coding 100, plus a case pinning that a ~300-char mount-failure body now survives intact. Fixes #3480. Supersedes #3481. --- packages/orchestrator/pkg/sandbox/envd.go | 5 ++++- packages/orchestrator/pkg/sandbox/envd_error_body_test.go | 8 ++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/orchestrator/pkg/sandbox/envd.go b/packages/orchestrator/pkg/sandbox/envd.go index cd9d68ce70..d76cf47b31 100644 --- a/packages/orchestrator/pkg/sandbox/envd.go +++ b/packages/orchestrator/pkg/sandbox/envd.go @@ -44,7 +44,10 @@ const ( maxEnvdResultBodySize = 1 << 20 // envdErrorBodyRunes is the length, in runes, an error or log line cuts a failed call's body to. - envdErrorBodyRunes = 100 + // envd error bodies are short server-generated diagnostics; 512 is enough to keep the actual + // cause of a failure intact (e.g. a volume-mount error carries the full chroot/bind path plus + // the errno text, ~300 chars) instead of cutting it mid-path, while still bounding the body. + envdErrorBodyRunes = 512 // envdErrorBodyLimit is the most of a failed call's body worth reading. Any // envdErrorBodyRunes runes fit in that many times utf8.UTFMax bytes, and the // extra byte lets Truncate still tell that a longer body was cut. diff --git a/packages/orchestrator/pkg/sandbox/envd_error_body_test.go b/packages/orchestrator/pkg/sandbox/envd_error_body_test.go index f57db7f64f..74940bcdf7 100644 --- a/packages/orchestrator/pkg/sandbox/envd_error_body_test.go +++ b/packages/orchestrator/pkg/sandbox/envd_error_body_test.go @@ -34,11 +34,15 @@ func TestEnvdErrorBodyMatchesAFullRead(t *testing.T) { "exactly 100 four-byte runes": strings.Repeat("😀", 100), "invalid utf-8": strings.Repeat("\xff", 1_000), "two-byte runes": strings.Repeat("é", 1_000), + // The bug this cap fixes: a volume-mount failure carries the full chroot/bind + // path plus the errno text (~300 chars). At the old 100-rune cap it was cut + // mid-path; at 512 it survives whole. + "volume mount failure (~300 chars)": `/init returned 400: failed to mount "vol-885b": failed to chroot into "/data1/orchestrator/volumes/team-f079aa21-3c4d-4e2a-9b1f-0123456789ab/vol-885b1234-abcd-ef01-2345-6789abcdef01": failed to bind mount "/srv/nfs/team-f079/vol-885b/ws_123.img": no such file or directory`, } { t.Run(name, func(t *testing.T) { t.Parallel() - assert.Equal(t, utils.Truncate(body, 100), envdErrorBody(strings.NewReader(body))) + assert.Equal(t, utils.Truncate(body, envdErrorBodyRunes), envdErrorBody(strings.NewReader(body))) }) } } @@ -73,7 +77,7 @@ func TestEnvdCallsReadABoundedBody(t *testing.T) { t.Parallel() const timeout = 10 * time.Second - truncated := strings.Repeat("e", 97) + "..." + truncated := strings.Repeat("e", envdErrorBodyRunes-len("...")) + "..." upgradeBin := filepath.Join(t.TempDir(), "envd") require.NoError(t, os.WriteFile(upgradeBin, []byte("binary"), 0o600))