bytebase/bytebase · error

failed to list indices: unexpected status code %d: %s

Error message

failed to list indices: unexpected status code %d: %s

What it means

In the basic-auth fallback of getIndices (sync.go:304), the _cat/indices response returned a non-200 status; the error includes the status code and the response body (e.g. an ES error JSON or auth challenge). Unlike the other wraps this is an errors.Errorf, not a wrap — the HTTP layer worked, the server said no.

Source

Thrown at backend/plugin/db/elasticsearch/sync.go:304

		return indicesMetadata, nil
	}

	// Fallback to basic auth client
	resp, err := d.basicAuthClient.Do("GET", []byte("/_cat/indices?format=json&pretty"), nil)
	if err != nil {
		return nil, errors.Wrapf(err, "failed to list indices")
	}
	defer resp.Body.Close()

	bytes, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, errors.Wrap(err, "failed to read indices response body")
	}

	// Check HTTP status code
	if resp.StatusCode != http.StatusOK {
		// Include response body for debugging
		return nil, errors.Errorf("failed to list indices: unexpected status code %d: %s", resp.StatusCode, string(bytes))
	}

	var results []IndicesResult
	if err := json.Unmarshal(bytes, &results); err != nil {
		// Include response body to help debug parsing issues
		bodyPreview, truncated := common.TruncateString(string(bytes), 500)
		if truncated {
			bodyPreview += "..."
		}
		return nil, errors.Wrapf(err, "failed to parse indices response: %s", bodyPreview)
	}

	for _, m := range results {
		if hiddenIndices[m.Index] {
			continue
		}

		datasize, err := unitConversion(m.IndexSize)

View on GitHub (pinned to 1870550677)

Solutions

  1. Read the body embedded in the error — it states whether it's auth (401/403), not-found (404), or unavailable (503).
  2. Fix credentials/permissions: ensure the user has monitor cluster + view index metadata privileges.
  3. Verify the base URL and any reverse-proxy path rewriting preserve /_cat/indices.
  4. If ES security is on, prefer the typed client with an API key over raw basic auth.

Example fix

// before
resp, err := d.basicAuthClient.Do("GET", []byte("/_cat/indices?format=json&pretty"), nil)
// after — check status before reading body semantics
resp, err := d.basicAuthClient.Do("GET", []byte("/_cat/indices?format=json"), nil)
if err != nil {
	return nil, errors.Wrapf(err, "failed to list indices")
}
if resp.StatusCode == http.StatusUnauthorized {
	return nil, errors.New("elasticsearch auth failed: check username/password")
}
Defensive patterns

Strategy: validation

Validate before calling

user, pass := instance.Credential
req, _ := http.NewRequest("GET", instanceURL+"/_cat/indices?format=json", nil)
req.SetBasicAuth(user, pass)
resp, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
if resp.StatusCode == 401 || resp.StatusCode == 403 {
	return fmt.Errorf("elasticsearch credentials/permissions invalid (HTTP %d)", resp.StatusCode)
}

Try / catch

if resp.StatusCode != http.StatusOK {
	body, _ := io.ReadAll(io.LimitReader(resp.Body, 1024))
	switch resp.StatusCode {
	case 401, 403:
		return fmt.Errorf("auth failed listing indices: %s", body)
	default:
		return fmt.Errorf("unexpected status %d: %s", resp.StatusCode, body)
	}
}

Prevention

When it happens

Trigger: basicAuthClient.Do returned a response with StatusCode != 200 — 401/403 wrong credentials, 404 wrong path/base-URL, 503 cluster unavailable, or a security plugin redirecting to a login page.

Common situations: Username/password wrong or rotated; user lacking privileges for _cat/indices; base URL path prefix wrong (e.g. behind a path-rewriting reverse proxy); Elasticsearch Security enabled but the driver configured without credentials.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of bytebase/bytebase@1870550677 (2026-09-06). Data as JSON: /api/errors/705562a3c700daae. Report an issue: GitHub.