cockroachdb / cockroachdb/cockroach

Malformed plan gist → AssertionFailedf("unhandled op %d") in getResultColumns

Open
#169,757 2 comments 0 reactions 0 assignees View on GitHub
C-bug O-community T-sql-queries X-blathers-triaged
Dominant language
Go
Stars
32.5k
Forks
4.1k
PR merge metrics
PR metrics pending

Description

## Describe the problem

For certain malformed plan gist strings passed to `crdb_internal.decode_external_plan_gist` (and similarly `decode_plan_gist`), decoding progresses far enough to construct an explain `exec` operator that **`getResultColumns` does not handle**, triggering:

```text
ERROR: internal error: unhandled op 59
```

(with the numeric op id depending on the corrupt payload).

The failure is an **`errors.AssertionFailedf`** in `pkg/sql/opt/exec/explain/result_columns.go` (`getResultColumns`), meaning **invalid external input** reaches an internal invariant failure instead of a user-facing validation error.

**Related prior work:** malformed gist handling was improved in [PR #109627](https://github.com/cockroachdb/cockroach/pull/109627) ([#110410](https://github.com/cockroachdb/cockroach/issues/110410), [#109560](https://github.com/cockroachdb/cockroach/issues/109560)). This report is a **post-fix / residual** case.

**Invariant framing:** this suggests that the decoder can construct exec operators that are **not covered by `getResultColumns`**, violating the implicit invariant that **all emitted operators must have corresponding column metadata**.

---

## To Reproduce

1. Start CockroachDB.

2. If required by your deployment:

```sql
SET allow_unsafe_internals = true;
```

3. Run:

```sql
SELECT * FROM crdb_internal.decode_external_plan_gist('AhwGAgw7BvU+bA==') LIMIT 1;
```

4. Observe `internal error: unhandled op 59` (or similar `unhandled op N`) with stack top:

- `pkg/sql/opt/exec/explain/result_columns.go` — `getResultColumns()`
- `pkg/sql/opt/exec/explain/explain_factory.go` — `newNode()`
- generated `plan_gist_factory.og.go` — `decodeOperatorBody`

```text
SET
ERROR: internal error: unhandled op 59
SQLSTATE: XX000
DETAIL: stack trace:
pkg/sql/opt/exec/explain/result_columns.go:258: getResultColumns()
pkg/sql/opt/exec/explain/explain_factory.go:107: newNode()
bazel-out/k8-fastbuild/bin/pkg/sql/opt/exec/explain/plan_gist_factory.og.go:1651: decodeOperatorBody()
pkg/sql/opt/exec/explain/plan_gist_factory.go:244: decodeOp()
pkg/sql/opt/exec/explain/plan_gist_factory.go:217: DecodePlanGistToPlan()
pkg/sql/opt/exec/explain/plan_gist_factory.go:187: DecodePlanGistToRows()
pkg/sql/plan_opt.go:1171: DecodeGist()
pkg/sql/sem/builtins/generator_builtins.go:998: Start()
pkg/sql/rowexec/project_set.go:208: nextInputRow()
pkg/sql/rowexec/project_set.go:302: Next()
pkg/sql/colexec/columnarizer.go:244: Next()
pkg/sql/colflow/stats.go:122: next()
pkg/sql/colexecerror/error.go:162: CatchVectorizedRuntimeError()
pkg/sql/colflow/stats.go:130: Next()
pkg/sql/colflow/flow_coordinator.go:244: nextAdapter()
pkg/sql/colexecerror/error.go:162: CatchVectorizedRuntimeError()
pkg/sql/colflow/flow_coordinator.go:248: next()
pkg/sql/colflow/flow_coordinator.go:302: Run()
pkg/sql/colflow/vectorized_flow.go:317: Run()
pkg/sql/distsql_running.go:1087: Run()
pkg/sql/distsql_running.go:2397: PlanAndRun()
pkg/sql/distsql_running.go:2096: func3()
pkg/sql/distsql_running.go:2099: PlanAndRunAll()
pkg/sql/conn_executor_exec.go:3694: execWithDistSQLEngine()
pkg/sql/conn_executor_exec.go:3185: dispatchToExecutionEngine()
pkg/sql/conn_executor_exec.go:1178: execStmtInOpenState()
pkg/sql/conn_executor_exec.go:183: func2()
pkg/sql/conn_executor_exec.go:4766: execWithProfiling()
pkg/sql/conn_executor_exec.go:182: execStmt()
pkg/sql/conn_executor.go:2498: func1()
pkg/sql/conn_executor.go:2503: execCmd()
pkg/sql/conn_executor.go:2411: run()
Failed running "sql"
```

---

## Expected behavior

- Decoder should **reject** corrupt gists before explain node construction **or** `getResultColumns` must handle every operator the decoder can emit.

- User-visible outcome should be a **regular SQL error**, not `XX000 internal error` / assertion from **`unhandled op`**.

---

## Environment

- **CockroachDB:** `v26.3.0-alpha.00000000-dev`, CCL, linux amd64, Go 1.26.2
- **OS:** Linux 4.18.0-553.el8_10.x86_64
- **Client:** `cockroach sql --insecure`

Jira issue: CRDB-63639

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.