Allowlist the expected FileLog bad-path reattach error in the upgrade check - #113983
Allowlist the expected FileLog bad-path reattach error in the upgrade check#113983groeneai wants to merge 5 commits into
Conversation
… check Upgrade check (amd_release) fails its "Error message in clickhouse-server.log" sub-test on a single benign line: <Error> StorageFileLog (test_1.filelog_bad_path_attach): The absolute data path should be inside `user_files_path`(/var/lib/clickhouse/user_files/) 04202_filelog_attach_path_outside_user_files ATTACHes a FileLog table whose path is outside user_files_path. ATTACH is LoadingStrictnessLevel::ATTACH (2), which is >= SECONDARY_CREATE (1), so the constructor takes the relaxed branch at src/Storages/FileLog/StorageFileLog.cpp:195-198 and logs at <Error> and returns instead of throwing BAD_ARGUMENTS. That branch is deliberate and is the branch the test exists to cover: refusing to load a table at reattach time would break server startup. The test's closing DROP is ignored here, because the upgrade check runs the client with --fake-drop (ignore_drop_queries_probability=1, gated on ASTDropQuery::Kind::Drop in InterpreterDropQuery.cpp:221). The table therefore survives into the upgrade restart, is re-attached, and re-logs the same line into the scanned log. The post-restart scrub had no entry for it. Add one scoped entry to the existing secondary pipe of that scrub, requiring the fixture table name and the message together. Bare parens are literals in BRE, so the pattern also requires the "StorageFileLog (db.table):" prefix shape; the escaped-group form would be looser and was rejected. The pattern stops before the backtick in `user_files_path`, since inside double quotes bash would perform command substitution there. Product logging is not touched. Lowering the LOG_ERROR to LOG_WARNING was rejected: it would change what users see in order to satisfy a CI scanner, and would hide a genuine misconfiguration. Validation: the pipeline was extracted verbatim from the runner and run under GNU grep 3.11 over a fixture log. Without the entry the sub-test emits FAIL; with it, OK. Five negative controls plus a prefix-shape control still surface: the same message on another table, a different message on the fixture table, and a different logger. Deleting the new line flips the fixture line back to being reported, so the entry is load-bearing rather than a pattern that matches nothing.
…tionale
The allowlist entry matched any table name ENDING in filelog_bad_path_attach,
so the same error from an unrelated table (prod.other_filelog_bad_path_attach)
would have been suppressed too. Require the StorageID separator: the logger name
is built as "StorageFileLog (" + getFullTableName() + ")" and getFullTableName()
is backQuoteIfNeed(db) + "." + backQuoteIfNeed(table), so the literal '.' is
always present and the genuine line still matches.
Also correct the reason the table survives the upgrade restart. It is not
--fake-drop: that is appended to args.client (tests/clickhouse-test:7089), which
.sh tests do not use, and the line bridging it into the .sh environment is
commented out (:5889, and :5574 in the v26.7 tree the upgrade check actually
runs). Measured on the failing run's own query_log, 0 of 15021 .sh DROP rows
carry ignore_drop_queries_probability while 21111 .sql rows do, and the
fake-drop branch's LOG_TEST lines appear 0 times in the pre-restart log.
The table persists because stress threads run with a fixed --database=test_N
(stress.py:271-272) and clickhouse-test skips its per-test teardown when
--database is set (need_cleanup = not args.database, :4046), so that shared
database is never dropped. Only those fixed-database threads leak the table,
which is why the failure is intermittent.
Validated against the failing run's 19.9 MB clickhouse-server.upgrade.log: with
the entry the scan output is empty, and with it deleted the output is
byte-identical to the 189-byte upgrade_error_messages.txt that CI uploaded.
Two prefix-extension negative controls are now part of the matcher's test matrix.
Internal second-model review (2 rounds, 0 blockers outstanding)An independent reviewer and a second model reviewed this change cold, twice. Round 1 raised two Round 1 — 2 majors, both AGREEd and fixed❌ The allowlist pattern was over-broad. ❌ The published root cause was false. The first revision attributed the table's survival to Round 2 — clean, plus one nit not fixed
Validation the review relied onRather than the synthetic fixture, the review used this run's own artifacts (PR #113781, sha Carrier coverage was re-derived independently: |
Pre-PR validation gate (click to expand)
Session id: cron:clickhouse-impl-slot-6:20260808-171700 |
|
cc @leshikus, could you review this? It adds one scoped |
|
Workflow [PR], commit [70cbee0] Summary: ✅ AI ReviewSummaryThis PR narrows the upgrade-check log scrub so it suppresses only the expected Final Verdict
|
CI finish ledger - 58245a2CI is fully finished on this head and there are no failing checks.
Session id: cron:our-pr-ci-monitor:20260809-013000 |
master gained four Backup-engine allowlist entries (ClickHouse#109042) plus a hung-check fix in the same two regions of tests/docker_scripts/upgrade_runner.sh that this branch edits, so the grep pipe conflicted. Resolved as a union: every allowlist filter master added is kept verbatim and the FileLog entry is appended after them. Verified that all 96 -e patterns present on master survive the resolution and that the net diff against master is still the reviewed 1 file / +5 / -0. A side-pick would have deleted a merged allowlist entry and re-reddened the upgrade check for someone else. The FileLog matcher keeps its reviewed scoping to the fixture table (`.filelog_bad_path_attach`), so a genuine bad-path error elsewhere still surfaces.
The rationale said the fixed-database tables are "never torn down", which overstates it: 04202 runs its own final DROP, and a fixed --database only stops clickhouse-test's framework-level cleanup. The table therefore survives only when stress stops the fixture before that DROP, after which no teardown runs from either side. Verified: the fixture drops the table at tests/queries/0_stateless/04202_filelog_attach_path_outside_user_files.sh:31, and tests/clickhouse-test:4025 gates only the framework _cleanup on `not args.database`. Comment only, no behaviour change.
Build profile diff (arm_release)Comparing ✅ No significant changes. Binary sizes
Only the stripped binary is compared: the official master build keeps debug symbols while PR builds strip them, so the other binaries differ by construction. Compile time of recompiled translation units6 translation units recompiled, 5 s compile time in total, 6 of them have a recent master baseline. |
The matcher used ".*" between the logger's closing paren and the message, so it also suppressed a line carrying interposed text between the two, for example "StorageFileLog (prod.filelog_bad_path_attach) prefix The absolute data path should be inside ...". That is wider than the contract of this entry, which is to allowlist exactly the one benign reattach line. OwnPatternFormatter writes the logger source and then ": " unconditionally (src/Loggers/OwnPatternFormatter.cpp:61-64), and colouring is off for the file channel that produces the scanned clickhouse-server.upgrade.log (src/Loggers/Loggers.cpp:159 takes the default color = false), so the two are always adjacent in that file and requiring the literal boundary cannot cause a miss. Verified with GNU grep 3.11 against the real 19.9 MB clickhouse-server.upgrade.log of the failing run: the target line is still suppressed, the surviving output is byte-identical to the CI-produced upgrade_error_messages.txt when the entry is removed, the delta between the two arms is exactly that one line, and 9 negative controls still surface, including the interposed-text shape. No allowlist entry from master is lost.
CI finish ledger - 70cbee0No failures to own on this head: 26 checks succeeded, 151 were skipped, and praktika reports
The high skip count is expected for this diff, which touches only Session id: cron:our-pr-ci-monitor:20260813-183000 |
Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):
...
Description
Upgrade check (amd_release)intermittently fails itsError message in clickhouse-server.logsub-test on one benign line:No product defect: the server starts, nothing crashes, no data is affected.
Root cause.
04202_filelog_attach_path_outside_user_filesATTACHes a FileLog table whose path is outsideuser_files_path.ATTACHisLoadingStrictnessLevel::ATTACH(2), which is>= SECONDARY_CREATE(1), so the constructor takes the relaxed branch atsrc/Storages/FileLog/StorageFileLog.cpp:195-198: it logs at<Error>and returns instead of throwingBAD_ARGUMENTS. That branch is deliberate and is what the test covers, since refusing to load at reattach time would break server startup. The table then outlives the test: stress threads run with a fixed--database=test_N(ci/jobs/scripts/stress/stress.py), andclickhouse-testskips its per-test teardown whenever--databaseis set (need_cleanup = not args.database), so that shared database is never dropped. The upgrade restart re-attaches the table, the relaxed branch fires again, and the line lands in the scanned log, where the post-restart scrub intests/docker_scripts/upgrade_runner.shhad no entry for it. Hence the intermittency:04202must land on a fixed-database thread.Change. One
grep -aventry in that scrub's existing secondary pipe, plus a short rationale comment next to the sibling entries. The pattern requires the fixture table name and the message together, and (bare parens are literals in BRE) theStorageFileLog (db.table):prefix shape. No source change, no test change.Validation. The scan pipeline, extracted verbatim from the runner, was run under GNU grep 3.11 against the failing run's own 19.9 MB
clickhouse-server.upgrade.log. With the entry the artifact is empty; with it deleted the output is byte-identical to the 189-byteupgrade_error_messages.txtCI produced, so the sub-test flipsFAILtoOK. Eight negative controls still surface, including a table whose name merely ends with the fixture name (prod.other_filelog_bad_path_attach), which the required.separator keeps visible.