shadow1ng/fscan · error
unexpected query opcode: %d
Error message
unexpected query opcode: %d
What it means
Guard in validateCQLQueryResponse: a post-auth QUERY exchange returned an opcode that is neither cqlOpResult nor cqlOpError. It fires when the Cassandra peer violates the expected RESULT/ERROR reply contract, so the query response cannot be validated.
Source
Thrown at plugins/services/cassandra.go:220
if bodyLen == 0 {
return opcode, []byte{}, nil
}
if bodyLen > maxCQLFrameBody {
return opcode, nil, fmt.Errorf("cassandra frame too large: %d", bodyLen)
}
body := make([]byte, bodyLen)
if _, err := io.ReadFull(conn, body); err != nil {
return opcode, nil, err
}
return opcode, body, nil
}
func validateCQLQueryResponse(opcode byte, body []byte) error {
if opcode == cqlOpError {
return fmt.Errorf("cassandra query failed: %s", string(body))
}
if opcode != cqlOpResult {
return fmt.Errorf("unexpected query opcode: %d", opcode)
}
return nil
}
// cqlStringMap CQL string map 编码: [2B count] [pairs: [2B len] [str]]
func cqlStringMap(m map[string]string) []byte {
var buf []byte
buf = append(buf, 0x00, byte(len(m))) // count as short
for k, v := range m {
buf = append(buf, cqlShortString(k)...)
buf = append(buf, cqlShortString(v)...)
}
return buf
}
func cqlShortString(s string) []byte {
b := []byte(s)
buf := make([]byte, 2+len(b))View on GitHub (pinned to 95cc12e753)
Solutions
- Log the opcode value and compare against the CQL native protocol opcode table to identify the mismatch.
- Ensure the auth-phase frames were fully consumed before sending the test query (no leftover bytes in the stream).
- Pin a supported protocol version and reconnect to resynchronize framing.
Defensive patterns
Strategy: retry
Try / catch
if err := validateCQLQueryResponse(opcode, body); err != nil && strings.HasPrefix(err.Error(), "unexpected query opcode") {
return reconnectAndRetry() // framing may be desynced
} Prevention
- Fully consume auth-phase frames before issuing the test query.
- Pin a supported protocol version to keep frame boundaries aligned.
- Verify no intermediary proxy is mangling the CQL stream.
When it happens
Trigger: validateCQLQueryResponse is called with an opcode that is neither cqlOpError nor cqlOpResult — e.g. the connection returned an AUTHENTICATE or SUPPORTS frame, or framing desynced so the opcode byte is garbage.
Common situations: Talking to an intermediary or non-Cassandra server mid-stream; protocol-version mismatch corrupting frame boundaries; reading a stale response left over from the auth phase.
Related errors
- unexpected opcode: %d
- cassandra error: %s
- cassandra frame too large: %d
- cassandra query failed: %s
- Unsupport FastPathPDU type 0x%x
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/de24a08696e2876f.
Report an issue: GitHub.