{"record":{"id":"76b8dee6c3ecbb15","repo":"owasp-amass/amass","slug":"listsessions-status-s-error-s","errorCode":null,"errorMessage":"listSessions: status=%s error=%s","messagePattern":"listSessions: status=(.+?) error=(.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/api/client/v1/client.go","lineNumber":128,"sourceCode":"\t\treturn uuid.UUID{}, err\n\t}\n\n\treturn uuid.Parse(out.SessionToken)\n}\n\n// Lists the active session and associated tokens on the server.\nfunc (c *Client) ListSessions(ctx context.Context) ([]uuid.UUID, error) {\n\tresp, err := amasshttp.RequestWebPage(ctx, c.httpClient, &amasshttp.Request{URL: c.base + \"/sessions/list\"})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif resp.StatusCode != http.StatusOK {\n\t\tmsg, err := readJSONError(resp.Body)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"listSessions: status=%s\", resp.Status)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"listSessions: status=%s error=%s\", resp.Status, msg)\n\t}\n\n\tvar out ListSessionsResponse\n\tif err := json.Unmarshal([]byte(resp.Body), &out); err != nil {\n\t\treturn nil, err\n\t}\n\n\ttokens := make([]uuid.UUID, 0, len(out.SessionTokens))\n\tfor _, t := range out.SessionTokens {\n\t\ttoken, err := uuid.Parse(t)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\ttokens = append(tokens, token)\n\t}\n\treturn tokens, nil\n}\n","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/owasp-amass/amass/blob/79299dce87b0085db0f2f4ef3e9c52cccb49f514/engine/api/client/v1/client.go#L110-L146","documentation":"This error is returned by Client.ListSessions when the amass engine server responds to GET /api/v1/sessions/list with a non-200 status. The error string embeds the HTTP status (e.g. '500 Internal Server Error') and, when the response body is a JSON error object that readJSONError can decode, the server's error message. It is the library's way of surfacing a server-side rejection of the session listing request.","triggerScenarios":"Calling ListSessions(ctx) when the server returns any status other than 200 for /api/v1/sessions/list: the API server is down or restarting behind a proxy (502/503), the request hits a wrong base URL that answers with 404, auth/permission middleware rejects the request (401/403), or the server's session store fails (500). The variant with 'error=' only occurs when the body parses as a JSON error; the variant without it occurs when the body is HTML, empty, or non-JSON (e.g. a proxy error page).","commonSituations":"Pointing the client at a base URL that serves the UI or a different API version instead of the engine API; the engine process crashed and a reverse proxy returns 502; misconfigured auth token so the endpoint returns 403; firewall/ingress returning an HTML error page that readJSONError cannot decode.","solutions":["Check the HTTP status embedded in the error: 404 usually means the base URL or API path is wrong - verify the URL passed to NewClient points at the engine's /api/v1 root","For 502/503, verify the engine server process is running and reachable (use HealthCheck before ListSessions) and restart it if needed","For 401/403, fix authentication/authorization on the server or the client's credentials","If the message lacks 'error=', capture the raw response body to see what non-JSON payload (HTML proxy page, empty body) the server returned","Retry with backoff for transient 5xx; report persistent 500s to the server operator with server logs"],"exampleFix":"// before: calling with the wrong base URL\nclient, _ := v1.NewClient(\"https://engine.example.com\") // serves UI, not API\n\n// after: point at the API root and health-check first\nclient, _ := v1.NewClient(\"https://engine.example.com\") // base becomes /api/v1\nif !client.HealthCheck(ctx) {\n    log.Fatal(\"engine API unreachable; check server and base URL\")\n}\ntokens, err := client.ListSessions(ctx)","handlingStrategy":"try-catch","validationCode":"// Go: gate on health before listing\nif !client.HealthCheck(ctx) {\n    return fmt.Errorf(\"engine API unreachable at %s\", baseURL)\n}","typeGuard":null,"tryCatchPattern":"// Go\nfunc listSessionsSafe(ctx context.Context, c *v1.Client) ([]uuid.UUID, bool, error) {\n    tokens, err := c.ListSessions(ctx)\n    if err == nil {\n        return tokens, false, nil\n    }\n    if s := err.Error(); strings.Contains(s, \"502\") || strings.Contains(s, \"503\") || strings.Contains(s, \"504\") {\n        return nil, true, err // retryable\n    }\n    return nil, false, err\n}","preventionTips":["Call HealthCheck before API calls and fail fast if the engine is down","Pass the correct API root URL to NewClient (it appends /api/v1)","Distinguish 4xx (do not retry) from 5xx (retry with backoff) using the status embedded in the error","Monitor the engine process so 502/503 from proxies is caught early"],"tags":["http","api","network","amass"],"backgroundTag":"http-error-response","analyzedSha":"79299dce87b0085db0f2f4ef3e9c52cccb49f514","analyzedAt":"2026-09-06T08:22:48.198Z","contentChangedAt":"2026-09-06T08:22:48.198Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}