{"record":{"id":"a54c997f8d0a1314","repo":"AdguardTeam/AdGuardHome","slug":"invalid-blocked-services-w","errorCode":null,"errorMessage":"invalid blocked services: %w","messagePattern":"invalid blocked services: %w","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/home/clientshttp.go","lineNumber":165,"sourceCode":"\t\tupsCacheSize = prev.UpstreamsCacheSize\n\t}\n\n\tif cj.IgnoreQueryLog != aghalg.NBNull {\n\t\tignoreQueryLog = cj.IgnoreQueryLog == aghalg.NBTrue\n\t}\n\n\tif cj.IgnoreStatistics != aghalg.NBNull {\n\t\tignoreStatistics = cj.IgnoreStatistics == aghalg.NBTrue\n\t}\n\n\tif cj.UpstreamsCacheEnabled != aghalg.NBNull {\n\t\tupsCacheEnabled = cj.UpstreamsCacheEnabled == aghalg.NBTrue\n\t\tupsCacheSize = cj.UpstreamsCacheSize\n\t}\n\n\tsvcs, err := copyBlockedServices(cj.Schedule, cj.BlockedServices, prev)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid blocked services: %w\", err)\n\t}\n\n\tif (uid == client.UID{}) {\n\t\tuid, err = client.NewUID()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"generating uid: %w\", err)\n\t\t}\n\t}\n\n\treturn &client.Persistent{\n\t\tBlockedServices:       svcs,\n\t\tUID:                   uid,\n\t\tIgnoreQueryLog:        ignoreQueryLog,\n\t\tIgnoreStatistics:      ignoreStatistics,\n\t\tUpstreamsCacheEnabled: upsCacheEnabled,\n\t\tUpstreamsCacheSize:    upsCacheSize,\n\t}, nil\n}","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/home/clientshttp.go#L147-L183","documentation":"Converting an incoming client JSON object to a client object failed because the blocked-services schedule/IDs copied from the request are invalid. The wrapped error details the schedule validation problem.","triggerScenarios":"POST/PUT /control/clients (add/update) with a BlockedServices list containing unknown service IDs or a malformed Schedule (bad ranges, unsupported day/hour values).","commonSituations":"Client code sending stale or invented service IDs after an upgrade removed/renamed them; hand-crafted JSON payloads; timezone/schedule format mistakes.","solutions":["Fetch the current list of valid blocked service IDs (GET /control/blocked_services/services) and use only those","Validate the Schedule object against the expected weekly-schedule schema before sending","Check the wrapped error message for the exact offending field"],"exampleFix":"// before\n{\"blocked_services\": [\"not_a_service\"]}\n// after\n{\"blocked_services\": [\"youtube\",\"tiktok\"]}","handlingStrategy":"validation","validationCode":"// Fetch valid service IDs first and intersect\nvalid, _ := getBlockedServiceIDs()\nreq.BlockedServices = intersect(req.BlockedServices, valid)","typeGuard":null,"tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"invalid blocked services\") {\n        // refresh IDs and retry once\n    }\n}","preventionTips":["Always source service IDs from the API, never hardcode","Validate schedule JSON shape client-side before submit"],"tags":["clients","blocked-services","validation","api"],"backgroundTag":"request-validation-failed","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}