projectdiscovery/nuclei · error

prompt not found (read cap reached)

Error message

prompt not found (read cap reached)

What it means

readUntil (pkg/utils/telnetmini/telnet.go:350) accumulates bytes and scans the lowercased buffer for the needles (prompts) you passed; if the buffer grows past Client.ReadCapBytes before any needle matches, it aborts with 'prompt not found (read cap reached)'. ReadCapBytes defaults to 64 KiB via Defaults() and is a memory safety cap for chatty endpoints. The partial text captured so far is returned with the error for diagnosis.

Source

Thrown at pkg/utils/telnetmini/telnet.go:350

						}
					}
				}
			default:
				// NOP for other commands (IAC NOP, GA, etc.)
			}
			continue
		}

		// regular data byte
		b.WriteByte(tmp[0])
		lower := strings.ToLower(b.String())
		for i, n := range lowNeedles {
			if strings.Contains(lower, n) {
				return needles[i], b.String(), nil
			}
		}
		if b.Len() > c.ReadCapBytes {
			return "", b.String(), errors.New("prompt not found (read cap reached)")
		}
	}
}

func (c *Client) setDeadlineFromCtx(ctx context.Context, write bool) {
	if ctx == nil {
		return
	}
	if dl, ok := ctx.Deadline(); ok {
		_ = c.Conn.SetReadDeadline(dl)
		if write {
			_ = c.Conn.SetWriteDeadline(dl)
		}
	}
}

func preview(s string, n int) string {
	if len(s) <= n {

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Pass the exact prompt string(s) the device prints as the `until` arguments to Exec
  2. Disable paging on the device first (e.g. `terminal length 0` on IOS) so output ends at the prompt
  3. Raise Client.ReadCapBytes when legitimate output exceeds 64 KiB
  4. Always set a ctx deadline so a truly missing prompt surfaces as context.DeadlineExceeded with partial output

Example fix

// before
c.ReadCapBytes = 4 * 1024
out, err := c.Exec(ctx, "show version", "#")

// after
c.ReadCapBytes = 512 * 1024
out, err := c.Exec(ctx, "terminal length 0\nshow version", "router# ")
Defensive patterns

Strategy: validation

Validate before calling

// sanity-check client config before issuing commands
c.Defaults() // ensures ReadCapBytes == 64 KiB and non-empty prompts
if len(c.ShellPrompts) == 0 {
    return errors.New("no shell prompts configured; Exec will hit read cap")
}
if c.ReadCapBytes < len(expectedOutput) {
    c.ReadCapBytes = 2 * len(expectedOutput)
}

Try / catch

out, err := c.Exec(ctx, cmd, "router# ")
if err != nil {
    if strings.Contains(err.Error(), "read cap reached") {
        // partial output is in `out`: inspect it to find the real prompt, adjust needles, retry once
        return retryWithPrompt(out)
    }
    return err
}

Prevention

When it happens

Trigger: Client.Exec(ctx, cmd, until...) where none of the `until` prompts appears in output; verbose commands (show-tech, large listings) exceeding 64 KiB; ReadCapBytes set small; prompt needles with different spacing/case than what the device prints (matching is on the lowercased accumulated string).

Common situations: Network templates running commands on devices with custom PS1 prompts; pager output ('--More--') interleaving; forgetting `terminal length 0`; banners repeating on every screen.

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/a2fbc80a6b41fcbe. Report an issue: GitHub.