{"record":{"id":"3b2c12a89cbba1d1","repo":"owasp-amass/amass","slug":"s-stats-status-s","errorCode":null,"errorMessage":"%s/stats: status=%s","messagePattern":"(.+?)/stats: status=(.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/api/client/v1/client.go","lineNumber":178,"sourceCode":"\t\t\treturn fmt.Errorf(\"terminateSession: status=%s\", resp.Status)\n\t\t}\n\t\treturn fmt.Errorf(\"terminateSession: status=%s error=%s\", resp.Status, msg)\n\t}\n\treturn nil\n}\n\n// Retrieves statistics for the session associated with the provided token.\nfunc (c *Client) SessionStats(ctx context.Context, token uuid.UUID) (*et.SessionStats, error) {\n\tresp, err := amasshttp.RequestWebPage(ctx, c.httpClient,\n\t\t&amasshttp.Request{URL: c.base + \"/sessions/\" + token.String() + \"/stats\"})\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(\"%s/stats: status=%s\", token.String(), resp.Status)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"%s/stats: status=%s error=%s\", token.String(), resp.Status, msg)\n\t}\n\n\tvar st et.SessionStats\n\tif err := json.Unmarshal([]byte(resp.Body), &st); err != nil {\n\t\treturn nil, err\n\t}\n\treturn &st, nil\n}\n\n// Retrieves scope for the session associated with the provided token.\nfunc (c *Client) SessionScope(ctx context.Context, token uuid.UUID, atype oam.AssetType) ([]oam.Asset, error) {\n\tsessionID := token.String()\n\tatypestr := strings.ToLower(string(atype))\n\tu := fmt.Sprintf(\"%s/sessions/%s/scope/%s\", c.base, sessionID, atypestr)\n\tresp, err := amasshttp.RequestWebPage(ctx, c.httpClient, &amasshttp.Request{URL: u})\n\tif err != nil {","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/owasp-amass/amass/blob/79299dce87b0085db0f2f4ef3e9c52cccb49f514/engine/api/client/v1/client.go#L160-L196","documentation":"Returned by Client.SessionStats when GET /api/v1/sessions/{token}/stats returns a non-200 status and the response body is not a decodable JSON error, so only the session token and HTTP status are reported. The format is '<token>/stats: status=<status>'. It indicates statistics could not be retrieved for that session.","triggerScenarios":"Calling SessionStats(ctx, token) (directly or via getStats) when the server returns a non-200 with a non-JSON body: the token refers to a session that has expired or been terminated (404), the request is rejected by auth middleware, a proxy serves an HTML error page (502/503), or the server returns an empty body on failure.","commonSituations":"Querying stats for a session terminated earlier in the run; stale token after an engine restart (in-memory sessions lost); load balancer or ingress returning non-JSON error pages; wrong base URL causing route misses.","solutions":["Check the status in the message: 404 usually means the session no longer exists - call ListSessions to confirm and obtain a live token","If the status is 502/503, verify the engine server is running (HealthCheck) and restart if needed","Ensure the token was created by the same server instance (CreateSession) and has not been terminated","Verify the NewClient base URL points at the engine API root","Capture the raw response to identify non-JSON bodies (proxy HTML) and fix the intervening infrastructure"],"exampleFix":"// before: using a token cached from a previous run\nst, err := client.SessionStats(ctx, cachedToken)\n\n// after: fall back to a live session token\ntokens, err := client.ListSessions(ctx)\nif err != nil || len(tokens) == 0 {\n    token, err = client.CreateSession(ctx, cfg)\n} else {\n    token = tokens[0]\n}\nst, err = client.SessionStats(ctx, token)","handlingStrategy":"try-catch","validationCode":"// Go: confirm the session exists before polling stats\nfunc ensureSession(ctx context.Context, c *v1.Client, token uuid.UUID, cfg *config.Config) (uuid.UUID, error) {\n    tokens, err := c.ListSessions(ctx)\n    if err != nil {\n        return uuid.UUID{}, err\n    }\n    for _, t := range tokens {\n        if t == token {\n            return token, nil\n        }\n    }\n    return c.CreateSession(ctx, cfg)\n}","typeGuard":null,"tryCatchPattern":"// Go\nst, err := c.SessionStats(ctx, token)\nif err != nil {\n    msg := err.Error()\n    if strings.Contains(msg, \"404\") {\n        return nil, fmt.Errorf(\"session %s no longer exists; recreate it\", token)\n    }\n    if strings.Contains(msg, \"502\") || strings.Contains(msg, \"503\") {\n        return backoffRetryStats(ctx, c, token)\n    }\n    return nil, err\n}","preventionTips":["Verify tokens against ListSessions before using them after any restart","Gate stats polling with HealthCheck","Use a single engine instance for create/stats/terminate to avoid token mismatch","If messages lack 'error=', check for proxies returning HTML error pages and bypass or fix them"],"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"}