{"record":{"id":"91c98f78e142bfbe","repo":"siyuan-note/siyuan","slug":"oidc-claim-rules-must-include-a-claim-and-at-least","errorCode":null,"errorMessage":"OIDC claim rules must include a claim and at least one value","messagePattern":"OIDC claim rules must include a claim and at least one value","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/oidc.go","lineNumber":540,"sourceCode":"\t\treturn errors.New(\"OIDC issuer URL is required\")\n\t}\n\tif (config.Provider == conf.OIDCProviderCustom || config.Provider == conf.OIDCProviderMicrosoft) && config.IssuerURL != \"\" {\n\t\tissuer, err := url.Parse(config.IssuerURL)\n\t\tif err != nil || issuer.Host == \"\" || issuer.User != nil || issuer.RawQuery != \"\" || issuer.Fragment != \"\" ||\n\t\t\t(issuer.Scheme != \"https\" && !util.IsLocalHostname(issuer.Hostname())) {\n\t\t\treturn errors.New(\"OIDC issuer URL must use HTTPS unless it is a loopback address\")\n\t\t}\n\t}\n\tif config.Provider != conf.OIDCProviderCustom && config.Provider != conf.OIDCProviderGoogle &&\n\t\tconfig.Provider != conf.OIDCProviderMicrosoft && config.Provider != conf.OIDCProviderGitHub {\n\t\treturn errors.New(\"Unsupported OIDC provider\")\n\t}\n\tif !config.AllowAll && len(config.ClaimRules) == 0 {\n\t\treturn errors.New(\"OIDC login requires at least one claim rule when Allow all users is disabled\")\n\t}\n\tfor _, rule := range config.ClaimRules {\n\t\tif rule == nil || rule.Claim == \"\" || len(rule.Values) == 0 {\n\t\t\treturn errors.New(\"OIDC claim rules must include a claim and at least one value\")\n\t\t}\n\t\tif rule.Operator != conf.OIDCClaimOperatorEquals && rule.Operator != conf.OIDCClaimOperatorContains {\n\t\t\treturn errors.New(\"Unsupported OIDC claim rule operator\")\n\t\t}\n\t\tfor _, value := range rule.Values {\n\t\t\tif value == \"\" {\n\t\t\t\treturn errors.New(\"OIDC claim rule values cannot be empty\")\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc ValidateOIDCMobileConfiguration(config *conf.OIDC) error {\n\tif err := ValidateOIDCConfiguration(config); err != nil {\n\t\treturn err\n\t}\n\tif config.Provider == conf.OIDCProviderGoogle {","sourceCodeStart":522,"sourceCodeEnd":558,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/oidc.go#L522-L558","documentation":"Eighth check in ValidateOIDCConfiguration (kernel/model/oidc.go:540): iterating ClaimRules, a rule is nil, its Claim field is empty, or its Values slice is empty. Each rule must name a claim (e.g. 'email', 'groups') and provide at least one value to match.","triggerScenarios":"Adding a claim rule via JSON/UI with a blank claim name, or with no values filled in; a rule object that deserialized to nil.","commonSituations":"Frontend bug that submits a rule row with the claim dropdown empty; hand-edited conf.json with a malformed rule entry.","solutions":["Open the OIDC claim rules editor and ensure each row has a non-empty claim name and at least one value.","Remove placeholder/empty rows before saving.","If editing JSON, ensure every element of ClaimRules is a complete object {Claim, Operator, Values}."],"exampleFix":"// before\ncfg.ClaimRules = []*conf.OIDCClaimRule{{Claim: \"\", Values: nil}}\n// after\ncfg.ClaimRules = []*conf.OIDCClaimRule{{Claim: \"email\", Operator: conf.OIDCClaimOperatorEquals, Values: []string{\"@corp.com\"}}}","handlingStrategy":"validation","validationCode":"for _, r := range cfg.ClaimRules {\n    if r == nil || r.Claim == \"\" || len(r.Values) == 0 {\n        return fmt.Errorf(\"incomplete claim rule: %%+v\", r)\n    }\n}","typeGuard":"func ruleComplete(r *conf.OIDCClaimRule) bool {\n    return r != nil && r.Claim != \"\" && len(r.Values) > 0\n}","tryCatchPattern":null,"preventionTips":["Frontend should validate each rule row before submit.","When migrating configs, drop empty placeholder rules rather than carrying them forward."],"tags":["oidc","claim-rules","config","validation"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}