vxcontrol/pentagi · error

unexpected status code: %d

Error message

unexpected status code: %d

What it means

traversaal.parseHTTPResponse rejects any non-200 status with 'unexpected status code: %d'. Statuses 429 or >=500 are wrapped as Retryable (transient server/load problems); everything else (400, 401, 403, 404...) is Fatal, meaning retrying the same engine will not help.

Source

Thrown at backend/pkg/tools/searchers/traversaal.go:106

		return "", Fatal(fmt.Errorf("failed to build request: %v", err))
	}

	req = req.WithContext(ctx)
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("x-api-key", t.apiKey())

	resp, err := client.Do(req)
	if err != nil {
		return "", Retryable(fmt.Errorf("failed to do request: %v", err), 0)
	}
	defer resp.Body.Close()

	return t.parseHTTPResponse(resp)
}

func (t *traversaal) parseHTTPResponse(resp *http.Response) (string, error) {
	if resp.StatusCode != http.StatusOK {
		err := fmt.Errorf("unexpected status code: %d", resp.StatusCode)
		if resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode >= 500 {
			return "", Retryable(err, 0)
		}
		return "", Fatal(err)
	}
	var respBody struct {
		Data traversaalSearchResult `json:"data"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&respBody); err != nil {
		return "", Fatal(fmt.Errorf("failed to decode response body: %v", err))
	}

	var writer strings.Builder
	writer.WriteString("# Answer\n\n")
	writer.WriteString(respBody.Data.Response)
	writer.WriteString("\n\n# Links\n\n")

	for i, resultLink := range respBody.Data.Links {

View on GitHub (pinned to ea665308ba)

Solutions

  1. Log and check the status code embedded in the message to pick the fix.
  2. For 401/403: verify the Traversaal API key configuration (x-api-key header source).
  3. For 400: inspect the query being sent; for 404: update traversaalURL to the current API endpoint.
  4. For 429/5xx: let the Retryable classification drive retry/fallback to another engine.

Example fix

// before: retrying all failures blindly
result, err := traversaal.Handle(ctx, req)
if err != nil { result, err = traversaal.Handle(ctx, req) }
// after: retry only Retryable, fail over otherwise
if err != nil && !searchers.IsRetryable(err) {
    return fallbackEngine.Handle(ctx, req)
}
Defensive patterns

Strategy: type-guard

Validate before calling

if os.Getenv("TRAVERSAAL_API_KEY") == "" {
    return errors.New("traversaal engine not configured; skipping")
}

Type guard

func classifySearcherError(err error) (retryable bool) {
    var r *searchers.RetryableError
    return errors.As(err, &r)
}

Try / catch

result, err := traversaalSearcher.Handle(ctx, req)
if err != nil {
    if classifySearcherError(err) {
        return retryWithBackoffOrFallback(req)
    }
    var f *searchers.FatalError
    if errors.As(err, &f) && strings.Contains(f.Error(), "401") {
        return "", fmt.Errorf("traversaal auth failed: check API key")
    }
    return fallbackEngine.Handle(ctx, req)
}

Prevention

When it happens

Trigger: search() receives any non-OK status from the Traversaal API and parseHTTPResponse builds fmt.Errorf("unexpected status code: %d", resp.StatusCode), then classifies: 429 or >=500 -> Retryable, otherwise Fatal.

Common situations: Invalid/missing Traversaal API key (401/403); malformed query rejected (400); rate limiting (429); Traversaal outage (5xx); endpoint path changed (404).

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/b35f832ab59fd442. Report an issue: GitHub.