{"record":{"id":"2865b56de5eba199","repo":"t8y2/dbx","slug":"unstable-result-shape-for-s","errorCode":null,"errorMessage":"unstable result shape for %s","messagePattern":"unstable result shape for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/iotdb/bench/go/main.go","lineNumber":168,"sourceCode":"\t\tFetchSize:     conf.FetchSize,\n\t\tWorkloads:     results,\n\t})\n}\n\nfunc runWorkload(session *client.Session, conf config, item workload) (workloadResult, error) {\n\tsamples := make([]float64, 0, item.Iterations)\n\tvar expected queryObservation\n\tfor index := 0; index < item.Iterations; index++ {\n\t\tstarted := time.Now()\n\t\tobservation, err := executeQuery(session, conf, item.SQL)\n\t\tif err != nil {\n\t\t\treturn workloadResult{}, err\n\t\t}\n\t\tsamples = append(samples, elapsedMS(started))\n\t\tif index == 0 {\n\t\t\texpected = observation\n\t\t} else if expected != observation {\n\t\t\treturn workloadResult{}, fmt.Errorf(\"unstable result shape for %s\", item.Name)\n\t\t}\n\t}\n\n\tordered := append([]float64(nil), samples...)\n\tsort.Float64s(ordered)\n\tvar total float64\n\tfor _, sample := range samples {\n\t\ttotal += sample\n\t}\n\treturn workloadResult{\n\t\tName:         item.Name,\n\t\tIterations:   item.Iterations,\n\t\tRows:         expected.Rows,\n\t\tDecodedCells: expected.DecodedCells,\n\t\tMeanMS:       roundMillis(total / float64(len(samples))),\n\t\tP50MS:        roundMillis(percentile(ordered, 0.50)),\n\t\tP95MS:        roundMillis(percentile(ordered, 0.95)),\n\t\tMinMS:        roundMillis(ordered[0]),","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/iotdb/bench/go/main.go#L150-L186","documentation":"runWorkload executes each workload item multiple times and compares every observation against the first iteration's result. If a later run returns a different shape/content ('expected != observation'), it aborts with 'unstable result shape for %s', because benchmarking a non-deterministic query would produce meaningless samples.","triggerScenarios":"A workload SQL (e.g. SHOW DATABASES after a create, or SELECT with volatile data) returns different rows/results across iterations while the bench loops through workload iterations.","commonSituations":"Point-query workload hitting data modified by another process during the run; metadata queries where a database/table was created between iterations; timing-affected ORDER BY without a deterministic tiebreaker.","solutions":["Make the workload SQL deterministic (fixed ORDER BY, stable predicates)","Ensure no concurrent writers modify the queried data during the benchmark","For capture workloads, run the capture phase before mutations, not interleaved","Wrap the comparison or update expected only when instability is intentional in main.go"],"exampleFix":"// before\n{Name: \"point_query\", SQL: \"SELECT * FROM root.db.d1\"}\n// after\n{Name: \"point_query\", SQL: \"SELECT s0 FROM root.db.d1 WHERE time = 1000\"}","handlingStrategy":"validation","validationCode":"func isDeterministicSQL(sql string) error {\n  low := strings.ToLower(sql)\n  if strings.Contains(low, \"select *\") && !strings.Contains(low, \"order by\") {\n    return fmt.Errorf(\"workload %q may be non-deterministic: add a deterministic ORDER BY\", sql)\n  }\n  return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use fixed ORDER BY on unique columns in workload SQL","Freeze the dataset (no concurrent writers) during benchmark runs","Run capture phase before any data mutations"],"tags":["benchmark","iotdb","determinism","sql"],"backgroundTag":"non-deterministic-query-result","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}