shadow1ng/fscan · error

oracle TTC unexpected message %d

Error message

oracle TTC unexpected message %d

What it means

While processing TTC (Two-Task Common) round-trip messages, the library received a message type it has no handler for in its switch. It aborts the round-trip with the numeric message type. This means the server sent an unexpected/unsupported TTC message during a statement execution or fetch.

Source

Thrown at plugins/services/oracle_raw.go:1622

			}
		}
	case 15:
		if _, err := s.getInt(2, true, true); err != nil {
			return err
		}
		length, err := s.getInt(2, true, true)
		if err != nil {
			return err
		}
		if _, err = s.getInt(2, true, true); err != nil {
			return err
		}
		if length > 0 {
			_, err = s.getClr()
			return err
		}
	default:
		return fmt.Errorf("oracle TTC unexpected message %d", msg)
	}
	return nil
}

func (s *oracleSession) readSummary() (*oracleSummary, error) {
	sum := &oracleSummary{}
	var err error
	if s.hasEOSCapability {
		if _, err = s.getInt(4, true, true); err != nil {
			return nil, err
		}
	}
	if s.ttcVersion >= 3 && s.hasFSAPCapability {
		if _, err = s.getInt(2, true, true); err != nil {
			return nil, err
		}
	}
	if _, err = s.getInt(4, true, true); err != nil {

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Note the reported message number and check whether the target Oracle version emits messages the library version doesn't handle; upgrade the library.
  2. Disable features that add TTC messages (e.g. DBMS_OUTPUT streaming, implicit results) if they correlate with the failure.
  3. Capture TNS traffic to identify the unexpected message and report it upstream as a protocol incompatibility.

Example fix

// before
rows, _ := stmt.QueryContext(ctx, q) // fails on implicit-result-capable call
// after: avoid calls returning implicit result sets, or upgrade lib
rows, _ := stmt.QueryContext(ctx, q) // with library >= version supporting msg type
Defensive patterns

Strategy: retry

Try / catch

err := runQuery(ctx, q)
if err != nil && strings.Contains(err.Error(), "TTC unexpected message") {
    // desync risk: recycle the connection instead of retrying on it
    conn.Close()
    return runQuery(ctx, q) // fresh connection
}

Prevention

When it happens

Trigger: A TTC round-trip reads a message byte that falls into the switch's default branch — e.g. an unexpected error, auth, or proprietary message during execute/fetch — instead of the handled result/row/summary message types.

Common situations: Server-side events the library doesn't model (e.g. implicit result sets on newer Oracle versions, end-of-call markers from a version mismatch); protocol desync after a previous parse error; connecting to Oracle versions that send extra TTC messages this implementation doesn't recognize.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/3277f680435b558e. Report an issue: GitHub.