{"record":{"id":"50549df9db145ca3","repo":"MHSanaei/3x-ui","slug":"w-for-email-s","errorCode":null,"errorMessage":"%w for email: %s","messagePattern":"%w for email: (.+?)","errorType":"exception","errorClass":"ErrClientNotInInbound","httpStatus":null,"severity":"warning","filePath":"internal/web/service/client_inbound_apply.go","lineNumber":936,"sourceCode":"\tvar newClients []any\n\tneedApiDel := false\n\tfound := false\n\n\tfor _, client := range interfaceClients {\n\t\tc, ok := client.(map[string]any)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tif cEmail, ok := c[\"email\"].(string); ok && cEmail == email {\n\t\t\tfound = true\n\t\t\tneedApiDel, _ = c[\"enable\"].(bool)\n\t\t} else {\n\t\t\tnewClients = append(newClients, client)\n\t\t}\n\t}\n\n\tif !found {\n\t\treturn false, fmt.Errorf(\"%w for email: %s\", ErrClientNotInInbound, email)\n\t}\n\tdb := database.GetDB()\n\tnewClients = compactOrphans(db, newClients)\n\tif newClients == nil {\n\t\tnewClients = []any{}\n\t}\n\tsettings[\"clients\"] = newClients\n\tnewSettings, err := json.MarshalIndent(settings, \"\", \"  \")\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tprevSettings := oldInbound.Settings\n\toldInbound.Settings = string(newSettings)\n\n\temailShared, err := inboundSvc.emailUsedByOtherInbounds(email, inboundId)\n\tif err != nil {\n\t\treturn false, err","sourceCodeStart":918,"sourceCodeEnd":954,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/web/service/client_inbound_apply.go#L918-L954","documentation":"Returned when removing a client from an inbound's settings JSON by email: after filtering the settings' clients array, no entry with that email was found, so the code refuses with ErrClientNotInInbound ('... for email: <email>'). The inbound's stored settings do not contain the client the caller expects.","triggerScenarios":"Calling DelInboundClientByEmail (directly or via the multi-inbound delete loops) with an email that is not present in that inbound's settings.clients — client already removed, email case/whitespace mismatch, or the client only exists in a client-record table but not in this inbound's JSON.","commonSituations":"Data drift between the clients table and inbound settings JSON (legacy upgrades, hand edits); retried deletes where the first attempt already succeeded; trailing space or different case in the email.","solutions":["Callers should treat this error as benign/idempotent — the delete loops already skip it; if you call it directly, do the same with errors.Is(err, ErrClientNotInInbound).","If the client SHOULD be there, inspect the inbound's settings JSON and the client record for email drift (spaces, case, duplicate entries).","Re-save the client on that inbound to re-sync settings JSON with the client table.","Trim/normalize emails on input so storage never accumulates whitespace variants."],"exampleFix":"// before: treating it as a hard failure\nerr := s.DelInboundClientByEmail(inboundSvc, ibId, email, keepTraffic, true)\nif err != nil { return err }\n\n// after: skip the idempotent not-present case\nif err != nil && !errors.Is(err, service.ErrClientNotInInbound) {\n    return err\n}","handlingStrategy":"validation","validationCode":"// Normalize and check presence before deleting from an inbound\nemail = strings.ToLower(strings.TrimSpace(email))\nif !inboundHasClient(ib, email) {\n    return nil // nothing to remove: treat as success\n}","typeGuard":"func IsClientNotInInbound(err error) bool {\n    return errors.Is(err, service.ErrClientNotInInbound)\n}","tryCatchPattern":"if _, err := s.DelInboundClientByEmail(inboundSvc, ibId, email, keepTraffic, true); err != nil {\n    if errors.Is(err, service.ErrClientNotInInbound) {\n        return false, nil // already absent — idempotent success\n    }\n    return false, err\n}","preventionTips":["Always skip ErrClientNotInInbound when calling the delete-by-email API directly.","Normalize emails (trim, case policy) at every entry point to prevent drift variants.","Re-save a client on its inbound after restoring/migrating DBs to re-sync settings JSON."],"tags":["client-management","idempotency","data-drift","validation"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}