shadow1ng/fscan · error

activemq_stomp_read_failed: %w

Error message

activemq_stomp_read_failed: %w

What it means

Guard in ActiveMQ authenticateSTOMP: reading the STOMP CONNECT response from the broker failed (I/O error or timeout after SetReadDeadline). The broker accepted the connection but never returned a readable frame, so credentials could not be verified.

Source

Thrown at plugins/services/activemq.go:177

func (p *ActiveMQPlugin) authenticateSTOMP(conn net.Conn, username, password string, config *common.Config) (bool, error) {
	timeout := config.ModuleTimeout()
	if err := rejectLineBreaks(username, password); err != nil {
		return false, err
	}

	stompConnect := fmt.Sprintf("CONNECT\naccept-version:1.0,1.1,1.2\nhost:/\nlogin:%s\npasscode:%s\n\n\x00",
		username, password)

	_ = conn.SetWriteDeadline(time.Now().Add(timeout))
	if _, err := conn.Write([]byte(stompConnect)); err != nil {
		return false, fmt.Errorf("%s: %w", i18n.GetText("activemq_stomp_send_failed"), err)
	}

	_ = conn.SetReadDeadline(time.Now().Add(timeout))
	response := make([]byte, 1024)
	n, err := conn.Read(response)
	if err != nil {
		return false, fmt.Errorf("%s: %w", i18n.GetText("activemq_stomp_read_failed"), err)
	}
	if n == 0 {
		return false, fmt.Errorf("%s", i18n.GetText("activemq_stomp_empty_response"))
	}

	responseStr := string(response[:n])

	if strings.Contains(responseStr, "CONNECTED") {
		return true, nil
	} else if strings.Contains(responseStr, "ERROR") {
		errorMsg := i18n.GetText("activemq_stomp_auth_error")
		if strings.Contains(responseStr, "Authentication failed") {
			errorMsg = "Authentication failed"
		} else if strings.Contains(responseStr, "Access denied") {
			errorMsg = "Access denied"
		} else if strings.Contains(responseStr, "Invalid credentials") {
			errorMsg = "Invalid credentials"
		}

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Increase the read timeout so slow brokers can answer
  2. Confirm the port actually serves STOMP (61613) and matches TLS settings
  3. Check broker logs for connection resets or authentication-plugin hangs
  4. Retry; transient network errors often clear on reconnect

Example fix

// before
n, err := conn.Read(response)
if err != nil {
    return false, fmt.Errorf("%s: %w", i18n.GetText("activemq_stomp_read_failed"), err)
}
// after (distinguish timeout from reset)
n, err := conn.Read(response)
if err != nil {
    if ne, ok := err.(net.Error); ok && ne.Timeout() {
        return false, fmt.Errorf("broker did not answer within %v", timeout)
    }
    return false, fmt.Errorf("%s: %w", i18n.GetText("activemq_stomp_read_failed"), err)
}
Defensive patterns

Strategy: retry

Validate before calling

// pre-check: confirm the port is reachable and tolerant of a probe
conn.SetReadDeadline(time.Now().Add(10 * time.Second))

Try / catch

n, err := conn.Read(buf)
if err != nil {
    if errors.Is(err, os.ErrDeadlineExceeded) { /* timeout: retry or fail fast */ }
    return fmt.Errorf("stomp read: %w", err)
}

Prevention

When it happens

Trigger: The read deadline (timeout) expires before the broker answers, the connection is reset, or the socket is closed while awaiting the CONNECTED/ERROR frame.

Common situations: Broker slow to respond beyond the configured timeout, TLS/plain mismatch (speaking STOMP to a TLS-only port), broker crash or restart mid-handshake, network device dropping the flow.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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