{"record":{"id":"8e1e1713b5939a63","repo":"owasp-amass/amass","slug":"terminatesession-status-s","errorCode":null,"errorMessage":"terminateSession: status=%s","messagePattern":"terminateSession: status=(.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/api/client/v1/client.go","lineNumber":160,"sourceCode":"\t\ttokens = append(tokens, token)\n\t}\n\treturn tokens, nil\n}\n\n// Terminates the session associated with the provided token.\nfunc (c *Client) TerminateSession(ctx context.Context, token uuid.UUID) error {\n\tresp, err := amasshttp.RequestWebPage(ctx, c.httpClient, &amasshttp.Request{\n\t\tMethod: http.MethodDelete,\n\t\tURL:    c.base + \"/sessions/\" + token.String(),\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif resp.StatusCode != http.StatusNoContent {\n\t\tmsg, err := readJSONError(resp.Body)\n\t\tif err != nil {\n\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)","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/owasp-amass/amass/blob/79299dce87b0085db0f2f4ef3e9c52cccb49f514/engine/api/client/v1/client.go#L142-L178","documentation":"Returned by Client.TerminateSession when the DELETE /api/v1/sessions/{token} call returns a status other than 204 No Content, and the response body is not a decodable JSON error (readJSONError failed). The error carries only the HTTP status. This is the library signaling that session termination did not succeed, without any server-provided detail.","triggerScenarios":"Calling TerminateSession(ctx, token) with a status other than 204 and a non-JSON/empty body: the session token was already terminated or never existed on this server (404 from a proxy or route mismatch), the server is down behind a load balancer (502/503), an auth middleware rejects the request, or the server returns plain-text/HTML errors instead of the expected JSON shape.","commonSituations":"Terminating a session twice (second DELETE finds no session); stale session token cached from a previous server instance; wrong base URL so DELETE hits an unknown route returning HTML 404; infrastructure (nginx/ALB) intercepting the request with a non-JSON error page.","solutions":["Check the embedded status: 404 typically means the session token is unknown or already terminated - re-list sessions with ListSessions and use a fresh token","Verify the engine server is up (HealthCheck) if the status is 502/503","Confirm the base URL given to NewClient points at the engine API root, not a UI or proxy path","If the token came from an earlier run, treat it as stale and create a new session instead of terminating","Retry once for transient 5xx; do not retry 4xx"],"exampleFix":"// before: terminating a possibly-stale token blindly\nerr := client.TerminateSession(ctx, staleToken)\n\n// after: verify the session still exists first\ntokens, err := client.ListSessions(ctx)\nif err != nil {\n    return err\n}\nfor _, t := range tokens {\n    if t == staleToken {\n        return client.TerminateSession(ctx, staleToken)\n    }\n}","handlingStrategy":"try-catch","validationCode":"// Go: verify the session still exists before terminating\nexists := false\nfor _, t := range mustListSessions(ctx, c) {\n    if t == token {\n        exists = true\n        break\n    }\n}\nif !exists {\n    return nil // nothing to terminate\n}","typeGuard":null,"tryCatchPattern":"// Go\nif err := c.TerminateSession(ctx, token); err != nil {\n    var retryable bool\n    switch {\n    case strings.Contains(err.Error(), \"404\"):\n        return nil // already gone\n    case strings.Contains(err.Error(), \"50\"):\n        retryable = true\n    }\n    if retryable {\n        return backoffRetry(func() error { return c.TerminateSession(ctx, token) })\n    }\n    return err\n}","preventionTips":["Track session lifecycle so you never terminate the same token twice","Re-list sessions (ListSessions) instead of reusing cached tokens across restarts","Keep engine and client versions in sync to avoid route mismatches","Treat missing 'error=' in the message as a non-JSON (proxy) response and inspect infrastructure"],"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"}