shadow1ng/fscan · error

oracle data type negotiation expected message 2, got %d

Error message

oracle data type negotiation expected message 2, got %d

What it means

In the second phase of the raw protocol handshake, the library expects the server's data type negotiation (dty) message with message type 2. A different message byte was received, so the handshake aborts with the actual value. This indicates the server or intermediary deviated from the expected TNS message sequence.

Source

Thrown at plugins/services/oracle_raw.go:1121

		for _, v := range typeReps {
			s.putBytes(uint8(v))
		}
		s.putBytes(0)
	} else {
		for _, v := range typeReps {
			s.putInt(v, 2, true, false)
		}
		s.putBytes(0, 0)
	}
	if err := s.writeData(); err != nil {
		return err
	}
	msg, err := s.getByte()
	if err != nil {
		return err
	}
	if msg != 2 {
		return fmt.Errorf("oracle data type negotiation expected message 2, got %d", msg)
	}
	if runtimeCaps[1] == 1 {
		if _, err = s.getBytes(11); err != nil {
			return err
		}
		if compileCaps[37]&2 == 2 {
			if _, err = s.getInt(4, false, true); err != nil {
				return err
			}
		}
	}
	level := 0
	for {
		var n int
		if compileCaps[27] == 0 {
			n, err = s.getInt(1, false, false)
		} else {
			n, err = s.getInt(2, false, true)

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Read the actual server message — often an ORA- error about login/DB state; fix the underlying login problem (credentials, account locked, database not open).
  2. Verify listener redirects aren't rewriting the stream; connect to the node the listener would redirect to.
  3. Capture TNS traffic and compare the message sequence against the library's expectations; report a server-version incompatibility if it's a consistent order difference.

Example fix

// Diagnostic: log server-side ORA error before dty stage
// before: handshake fails with 'expected message 2, got 4'
// after: check alert.log / listener.log for ORA- errors at connect time and fix e.g. locked account:
//   ALTER USER app_user ACCOUNT UNLOCK;
Defensive patterns

Strategy: try-catch

Try / catch

if err := connect(); err != nil {
    if strings.Contains(err.Error(), "expected message 2") {
        // server refused/redirected mid-handshake: check credentials and listener.log
    }
}

Prevention

When it happens

Trigger: The data-type negotiation step of the connect sequence reads a message byte that is not 2 — e.g. the server sent an error/redirect/refuse packet (type 4/9/11) instead of proceeding to dty negotiation.

Common situations: Server refuses the connection (wrong credentials, DB not open) and sends an error message where dty was expected; listener redirect responses; protocol version mismatch between client's negotiated version (4/5/6) and what the server then sends.

Related errors


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