Skip to content

[Umbrella] Nightly fuzzer failures: SQLancer, SQLancer++ and the data lake fuzzer #128538

Open

Description

@fm4v

Umbrella issue for every failure reported by the jobs of the NightlySQLancer workflow (ci/workflows/nightly_sqlancer.py, every 3 days on master, on an arm_release and an arm_asan_ubsan build):

  • SQLancer (arm_release), SQLancer (arm_asan_ubsan): the ClickHouse SQLancer provider (ci/jobs/sqlancer_job.sh). Findings are deduplicated into distinct failures in failures/analysis.txt, with one reproducer log per finding.
  • SQLancerPP (arm_release), SQLancerPP (arm_asan_ubsan): SQLancer++ (ci/jobs/sqlancer_pp_job.sh).
  • Data lake fuzzer (arm_release), Data lake fuzzer (arm_asan_ubsan): the data lake foreign-writer fuzzer (ci/jobs/datalake_fuzzer_job.py, tests/datalake_fuzzer/). Each failure report has the writer, the seed, the failing check with query, settings and row diff, the shrunk operation list and a replay command; the minimal histories are in datalake_fuzzer_logs.tar.zst.

How to handle a red run:

  1. For each distinct failure, check whether it is a real ClickHouse bug, a known issue, or a problem of the fuzzer or the job itself.
  2. A real bug: search for an existing issue. If there is none, open one with a minimal reproducer (SQL, or for the data lake fuzzer the writer steps and the ClickHouse query), the build and the link to the CI report, and add Related: <link to this issue>. Comment here with the link.
  3. A data lake fuzzer finding that would fire on every run until fixed: add a gate in tests/datalake_fuzzer/foreign_writer_fuzz/known_issues.py that links the new issue. When an issue is closed, remove its gate so the fuzzer guards the fix.
  4. A fuzzer or job problem (false positive, harness error, infrastructure): fix it in the job or the fuzzer.

Keep this issue open; it collects the links to all findings.

Related: #128295

Data lake fuzzer gates (as of 2026-11-02)

The gates in tests/datalake_fuzzer/foreign_writer_fuzz/known_issues.py keep the fuzzer away from open bugs. When an issue below is closed, remove its gate so the fuzzer guards the fix.

Enabled again in #128557, the fixes were merged on 2026-11-01:

Still gated, because a local run on master 26.11.1.1039 failed on them once the gates above were removed:

Still gated, issues open:

Activity

  1. added
    testingSpecial issue with list of bugs found by CI
    fuzzProblem found by one of the fuzzers
    on Nov 1, 2026
  2. self-assigned this
    on Nov 1, 2026
  3. fm4v commented on Nov 1, 2026

    @fm4v
    MemberAuthor

    @groeneai please take ownership of this umbrella issue: triage every failure of the SQLancer, SQLancerPP and Data lake fuzzer jobs in the NightlySQLancer workflow as described above, open an issue for each new ClickHouse bug with a minimal reproducer, link it here, and fix fuzzer or job problems directly.

  4. fm4v commented on Nov 1, 2026

    @fm4v
    MemberAuthor

    Data lake fuzzer findings on master 26.11.1.1039 (local run while removing the gates of fixed issues):

  5. groeneai commented on Nov 1, 2026

    @groeneai
    Collaborator

    Acknowledged, I am taking ownership of this. I will triage the latest NightlySQLancer run and every red run after it as described above, and post the issue and fix-PR links here.

  6. fm4v commented on Nov 1, 2026

    @fm4v
    MemberAuthor

    One more data lake fuzzer finding from the same local run:

    Gates are updated in #128557.

  7. groeneai commented on Nov 2, 2026

    @groeneai
    Collaborator

    Triage of the latest run, c189bd99fbda (2026-11-01). Every failure already has a fix. All of them merged after this run, so the 2026-11-04 run is the first one that includes them.

    Job Failure Cause Fixed by
    SQLancer (both builds) DistributedPlanEquivalence, Code 139 NO_ELEMENTS_IN_CONFIG (x2003 / x2074, fills the 2000-finding cap) ClickHouse: the error code changed in #124938 #126660
    SQLancer (arm_asan_ubsan) CERT, more-restrictive query has higher estimated cardinality (10000 > 9999) fuzzer: a background merge between the two estimates ClickHouse/sqlancer#24
    SQLancer (arm_asan_ubsan) TLPWhere, Code 47 reading view v87 after RENAME COLUMN on its table fuzzer: a view broken by its own ALTER ClickHouse/sqlancer#23
    SQLancer (arm_release) ALTER TABLE t1 UPDATE c0 = c2 with c0 ALIAS c2, Code 16 fuzzer: a mutation assigns an ALIAS column ClickHouse/sqlancer#26

    SQLancerPP is green on both builds. The data lake fuzzer has not run on master yet.

    Still open from earlier runs (last 30 days):

    • SQLancerPP NoREC / WHERE / QUERY_PARTITIONING (arm_release, latest 2026-10-31): a real bug. -0. and 0. are different keys in a hash join, so a cross join rewritten into a hash join loses rows: SELECT count() FROM (SELECT -0. AS a) AS t1 JOIN (SELECT 0 AS b) AS t2 ON a = b returns 0. Existing issue Merging a cross-type equality into a join condition changes its semantics for float supertypes (-0.0 stops matching 0) #116358, fix in Make hash tables agree with equals on negative zero #115970.
    • SQLancer unknown oracle, Code 16 on CREATE TABLE (2026-10-28): the generator passes a column that it rendered as EPHEMERAL or ALIAS as an engine parameter (SummingMergeTree(c2), the Collapsing sign).
    • SQLancer TLPWhere result-set mismatch (2026-10-22): a failed mutation succeeds on a background retry between the oracle's two reads. The unfinished-mutation check uses a schema read from before the mutations ran.
    • SQLancer ColumnTransformer, Code 32 (2026-10-19): the oracle picks a table with an unfinished MODIFY COLUMN mutation because it does not use the stable-table filter.

    The last three are fuzzer problems. I am fixing them in ClickHouse/sqlancer and will post the PR links here.

  8. groeneai commented on Nov 2, 2026

    @groeneai
    Collaborator

    SQLancer ColumnTransformer, Code 32 (2026-10-19): fixed in ClickHouse/sqlancer#27, the oracle now picks only tables that are stable for repeated reads.

  9. groeneai commented on Nov 2, 2026

    @groeneai
    Collaborator

    SQLancer TLPWhere result-set mismatch (2026-10-22): fixed in ClickHouse/sqlancer#28. The unfinished-mutation check now uses the schema as it is when testing starts, and it also covers views over such tables.

  10. groeneai commented on Nov 2, 2026

    @groeneai
    Collaborator

    SQLancer unknown oracle, Code 16 at CREATE TABLE (2026-10-28): fixed in ClickHouse/sqlancer#29. The generator now picks engine parameter columns (columns to sum, sign, version) only from columns that are not EPHEMERAL or ALIAS.

  11. changed the title [-]Nightly fuzzer failures: SQLancer, SQLancer++ and the data lake fuzzer[/-] [+][Umbrella] Nightly fuzzer failures: SQLancer, SQLancer++ and the data lake fuzzer[/+] on Nov 2, 2026
  12. 3 remaining items

  13. groeneai commented on Nov 7, 2026

    @groeneai
    Collaborator

    Data lake fuzzer (arm_asan_ubsan), run 233269369bec (2026-11-07), spark_hudi seed 997843244: new issue #129909. A Spark write that failed left a 4-byte base file of an uncompleted instant, and the Hudi reader picked it over the last committed one (Parquet file too short: 4 bytes). It does not fire on every run, so no gate. I am preparing the fix.

  14. groeneai commented on Nov 7, 2026

    @groeneai
    Collaborator

    Data lake fuzzer (arm_asan_ubsan), run 233269369bec (2026-11-07), spark_hudi seed 997843263, content check: a fuzzer false positive, not a ClickHouse bug. The row was written with c1 = '', which Hudi stores in the same c1=__HIVE_DEFAULT_PARTITION__ directory as a NULL. Spark's Hudi read returns NULL for both rows there, while ClickHouse returns the stored ''. It fires on almost every Hudi table partitioned by a string column. Fixed in the fuzzer by #129922: the Hudi writer writes an empty partition string as NULL.

  15. groeneai commented on Nov 7, 2026

    @groeneai
    Collaborator

    Data lake fuzzer (arm_asan_ubsan), run 233269369bec (2026-11-07), pyiceberg_rest seed 997843258, filter check: new issue #129910. PyIceberg stores truncate[10](-2147483648) as the 32-bit wraparound 2147483646, and ClickHouse's partition pruning compares it with -2147483650, so it skips the file. I am preparing the fix.

  16. groeneai commented on Nov 7, 2026

    @groeneai
    Collaborator

    Data lake fuzzer, run 233269369bec (2026-11-07), clickhouse_iceberg foreign_disagree in both jobs (arm_asan_ubsan seed 997843243, arm_release seed 228157026): after two appends and an UPDATE on a bucket-partitioned table, Spark returns the rows that the UPDATE replaced, PyIceberg does not. Existing issue #125366, fix #119514 (open). Since #118596 the bucket value is written as Avro long under the spec's int partition type, and Iceberg 1.11 never matches such a non-null tuple (StructLikeWrapper.equals returns false on the type error). So Spark skips every ClickHouse delete file that covers more than one data file of a partition, while single-file and NULL-partition deletes still apply, which accounts for exactly the 19 and 61 extra rows.

  17. groeneai commented on Nov 7, 2026

    @groeneai
    Collaborator

    Data lake fuzzer (arm_release), run 233269369bec (2026-11-07), spark_iceberg seeds 228157056 and 228157080, query_error: new issue #129912. A truncate partition on a decimal(9,6) or decimal(28,28) column makes every read of the table fail, because icebergTruncate throws DECIMAL_OVERFLOW for such scales and rejects Decimal128. I am preparing the fix.

  18. groeneai commented on Nov 7, 2026

    @groeneai
    Collaborator

    Data lake fuzzer (arm_release), run 233269369bec (2026-11-07), pyiceberg_rest seed 228157089, filter check: new issue #129913. Manifest-list partition pruning reads the per-field partition summaries as a range of tuples, so it skips a manifest whose matching row has an inner value in the first partition column and NULL in a later one. The arm_asan_ubsan job of the same run did not report it, so no gate. I am preparing the fix.

  19. groeneai commented on Nov 7, 2026

    @groeneai
    Collaborator

    Data lake fuzzer (arm_asan_ubsan), run 233269369bec (2026-11-07), clickhouse_iceberg seed 997843259: also failed at an UPDATE on a truncate[4] over int v2 table, reported under the same signature as seed 997843243. icebergTruncate returns Int64 for Int32, so it is the same long-vs-int partition type: existing issue #118905 (open). #129925 gates both shapes in known_issues.py until the fixes land.

  20. groeneai commented on Nov 11, 2026

    @groeneai
    Collaborator

    Data lake fuzzer (arm_release), run f4435fcbb66e (2026-11-10), pyiceberg_rest seed 205081375, filter check: a fuzzer false positive, not a ClickHouse bug. The table is partitioned by bucket[16] over a decimal(1,0) column. PyIceberg 0.11.1 writes bucket partition values with pyiceberg-core, which its pin (pyiceberg-core<0.9.0) resolves to 0.8.0 in the runner image. That version hashes a negative decimal over all 16 bytes (FF..F7 for -9) instead of the minimal two's-complement bytes the spec requires (F7), and drops the leading zero byte of a positive one whose top byte has the high bit set, such as 128; fixed in apache/iceberg-rust#1998 (0.9.0). So the -9 rows land in bucket 0, while the spec, PyIceberg's own BucketTransform.transform and ClickHouse's icebergBucket all give bucket 8, and partition pruning skips their file. About 5% of pyiceberg_rest histories partition a decimal by bucket (48 of 1000 seeds). Fuzzer fix: #130684.

  21. rschu1ze commented on Nov 11, 2026

    @rschu1ze
    Member

    @groeneai Ignore this finding from earlier runs:

    SQLancerPP NoREC / WHERE / QUERY_PARTITIONING (arm_release, latest 2026-10-31): a real bug. -0. and 0. are different keys in a hash join, so a cross join rewritten into a hash join loses rows: SELECT count() FROM (SELECT -0. AS a) AS t1 JOIN (SELECT 0 AS b) AS t2 ON a = b returns 0. Existing issue #116358, fix in #115970.

    We documented and will ignore the behavior going forward (#112409).

  22. groeneai commented on Nov 12, 2026

    @groeneai
    Collaborator

    Understood. I removed it from the triage and will not report it again. I will skip the IN set variant of the same cause as well: on master, -0. NOT IN (0) returns 1 while -0. != 0 returns 0.

  23. alexey-milovidov commented on Nov 13, 2026

    @alexey-milovidov
    Member

    Master nightly run 2026-11-13 (b271a92907b443c86ef632b67deb57d4b222f590), Data lake fuzzer (arm_release) and Data lake fuzzer (arm_asan_ubsan):
    https://s3.amazonaws.com/clickhouse-test-reports/praktika.html?REF=master&sha=b271a92907b443c86ef632b67deb57d4b222f590&name_0=NightlySQLancer&name_1=Data%20lake%20fuzzer%20%28arm_release%29
    https://s3.amazonaws.com/clickhouse-test-reports/praktika.html?REF=master&sha=b271a92907b443c86ef632b67deb57d4b222f590&name_0=NightlySQLancer&name_1=Data%20lake%20fuzzer%20%28arm_asan_ubsan%29

    SQLancerPP (arm_release), QUERY_PARTITIONING: SELECT * FROM database2_t0 returned 5 rows, the WHERE c0 / WHERE NOT c0 / WHERE c0 IS NULL partition 3 (seed 1794553936733). The logged database state (CREATE TABLE database2_t0 (c0 BOOLEAN, c1 VARCHAR, c2 INT, c3 VARCHAR, PRIMARY KEY (c2, c0, c1)), 3 inserts, DELETE ... WHERE c0, 5 inserts) gives the correct 2 + 3 + 0 with the same build (clickhouse local, and a server over HTTP with mutations_sync = 2), so the result depends on queries of the iteration that are not in the reproducer. The server error log has no exception for the oracle query. Candidates: the query condition cache poisoned by an earlier JOIN or outer filter over the same WHERE database2_t0.c0 (#123845, #121946), or SQLancer++ taking a truncated chunked HTTP response as a complete result (952 Premature end of chunk coded message body in this run). Not filed separately for lack of a self-contained reproducer.
    https://s3.amazonaws.com/clickhouse-test-reports/praktika.html?REF=master&sha=b271a92907b443c86ef632b67deb57d4b222f590&name_0=NightlySQLancer&name_1=SQLancerPP%20%28arm_release%29

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

comp-ci-infrastructureCI/CD pipelines (GitHub Actions, CI scripts, runners).fuzzProblem found by one of the fuzzerstestingSpecial issue with list of bugs found by CI

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions