{"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":484,"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":466,"sourceCodeEnd":502,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/oidc.go#L466-L502","documentation":"Each claim rule must name a claim key and list at least one accepted value; a nil rule, an empty Claim string, or an empty Values slice is meaningless as an access filter, so ValidateOIDCConfiguration rejects it.","triggerScenarios":"Iterating config.ClaimRules in ValidateOIDCConfiguration: any rule that is nil, has rule.Claim == \"\", or has len(rule.Values) == 0.","commonSituations":"Frontend submits a partially-filled rule row; JSON payload omits 'values' or 'claim' fields; programmatic config building appends an empty placeholder rule.","solutions":["Set a non-empty Claim name (e.g. 'email', 'groups') on every rule","Provide at least one non-empty entry in each rule's Values array","Remove empty/placeholder rules from the ClaimRules array before submitting"],"exampleFix":"// before\nClaimRules: []*conf.OIDCClaimRule{{Claim: \"\", Values: nil}}\n// after\nClaimRules: []*conf.OIDCClaimRule{{Claim: \"groups\", Values: []string{\"siyuan-users\"}, Operator: conf.OIDCClaimOperatorContains}}","handlingStrategy":"validation","validationCode":"const valid = Array.isArray(rules) && rules.every(r => r && typeof r.claim === 'string' && r.claim.length > 0 && Array.isArray(r.values) && r.values.length > 0);","typeGuard":"const isFilledRule = (r) => !!r && typeof r.Claim === 'string' && r.Claim !== '' && Array.isArray(r.Values) && r.Values.length > 0;","tryCatchPattern":"if err := ValidateOIDCConfiguration(cfg); err != nil {\n    if strings.Contains(err.Error(), \"claim and at least one value\") { /* repair rule */ }\n}","preventionTips":["Validate rule rows client-side before saving","Strip empty placeholder rows from the form before submit","Use typed constructors for rules that require claim and values"],"tags":["oidc","validation","schema"],"backgroundTag":"empty-required-field","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}