{"record":{"id":"b081eccb3f9c07b3","repo":"Kareadita/Kavita","slug":"series-restricted-age-restriction","errorCode":"series-restricted-age-restriction","errorMessage":"series-restricted-age-restriction","messagePattern":"series-restricted-age-restriction","errorType":"exception","errorClass":"KavitaNotFoundException","httpStatus":404,"severity":"warning","filePath":"Kavita.Server/Controllers/SeriesController.cs","lineNumber":630,"sourceCode":"                return BadRequest(await localizationService.TranslateAsync(\"generic-error\"));\n            }\n        }\n\n        if (ret == null) return BadRequest(await localizationService.TranslateAsync(\"generic-error\"));\n\n        var user = await unitOfWork.UserRepository.GetUserByIdAsync(UserId, ct: ct);\n        var restriction = new Models.Entities.AgeRestriction\n        {\n            AgeRating = user?.AgeRestriction ?? AgeRating.NotApplicable,\n            IncludeUnknowns = user?.AgeRestrictionIncludeUnknowns ?? true\n        };\n        var settings = await unitOfWork.SettingsRepository.GetMetadataSettingDto(ct);\n        var effectiveRating = RecommendationHelper.ComputeExternalAgeRating(ret.AgeRating,\n            ret.Genres ?? [], (ret.Tags ?? []).Select(t => t.Name), settings);\n\n        if (!RecommendationHelper.IsWithinAgeRestriction(effectiveRating, restriction))\n        {\n            throw new KavitaNotFoundException(await localizationService.TranslateAsync(\"series-restricted-age-restriction\"));\n        }\n\n        return Ok(ret);\n    }\n\n    /// <summary>\n    /// Based on the delta times between when chapters are added, for series that are not Completed/Cancelled/Hiatus, forecast the next\n    /// date when it will be available.\n    /// </summary>\n    /// <param name=\"seriesId\"></param>\n    /// <returns></returns>\n    [SeriesAccess]\n    [HttpGet(\"next-expected\")]\n    public async Task<ActionResult<NextExpectedChapterDto>> GetNextExpectedChapter(int seriesId)\n    {\n        var userId = UserId;\n        var ct = HttpContext.RequestAborted;\n","sourceCodeStart":612,"sourceCodeEnd":648,"githubUrl":"https://github.com/Kareadita/Kavita/blob/9c3e5400007f8a0282f7d883f2ad5e71716e514d/Kavita.Server/Controllers/SeriesController.cs#L612-L648","documentation":"Thrown as KavitaNotFoundException with the localized 'series-restricted-age-restriction' key by SeriesController's external-series-detail endpoint when the computed effective age rating of the external series exceeds the requesting user's AgeRestriction (RecommendationHelper.IsWithinAgeRestriction returns false). ExceptionMiddleware maps KavitaNotFoundException to HTTP 404 NotFound with no body.","triggerScenarios":"A user with an age restriction (e.g. restricted to Teen) requests external series detail (AniList/MAL/MangaBaka) for a series whose effective rating is above their limit. The effective rating is computed from the series rating plus its genres/tags via RecommendationHelper.ComputeExternalAgeRating.","commonSituations":"A restricted (child/age-limited) account browses to a mature series recommendation; metadata settings inflate the effective rating; tags/genres push a borderline series above the threshold.","solutions":["Have an admin raise (or remove) the user's AgeRestriction if the content is appropriate.","Accept the restriction — this is intended behavior protecting age-limited users.","Review the series tags/genres if a clearly-safe series is being over-rated."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"var restriction = new AgeRestriction {\n    AgeRating = user?.AgeRestriction ?? AgeRating.NotApplicable,\n    IncludeUnknowns = user?.AgeRestrictionIncludeUnknowns ?? true };\nif (!RecommendationHelper.IsWithinAgeRestriction(effectiveRating, restriction))\n    return NotFound();","typeGuard":null,"tryCatchPattern":"try { return Ok(await GetSeriesDetail(...)); }\ncatch (KavitaNotFoundException) { return NotFound(); }","preventionTips":["Filter recommendations by the user's restriction client-side.","Keep AgeRestriction current for age-limited accounts.","Review tags/genres inflating effective ratings."],"tags":["series","age-restriction","access-control","recommendation"],"backgroundTag":null,"analyzedSha":"9c3e5400007f8a0282f7d883f2ad5e71716e514d","analyzedAt":"2026-08-13T19:06:05.897Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}