{"record":{"id":"a846be773c8b4e7d","repo":"ory/kratos","slug":"failed-to-unmarshal-webhook-configuration-for-s","errorCode":null,"errorMessage":"failed to unmarshal webhook configuration for %s: %w","messagePattern":"failed to unmarshal webhook configuration for (.+?): %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"driver/registry_default_hooks.go","lineNumber":88,"sourceCode":"func getHooks[T any](m *RegistryDefault, credentialsType string, configs []config.SelfServiceHook) ([]T, error) {\n\thooks := make([]T, 0, len(configs))\n\n\tvar addSessionIssuer bool\nallHooksLoop:\n\tfor _, hookConfig := range configs {\n\t\tswitch hookConfig.Name {\n\t\tcase hook.KeySessionIssuer:\n\t\t\t// The session issuer hook always needs to come last.\n\t\t\taddSessionIssuer = true\n\t\tcase hook.KeySessionDestroyer:\n\t\t\tif h, ok := any(m.HookSessionDestroyer()).(T); ok {\n\t\t\t\thooks = append(hooks, h)\n\t\t\t}\n\t\tcase hook.KeyWebHook:\n\t\t\tcfg := request.Config{}\n\t\t\tif err := json.Unmarshal(hookConfig.Config, &cfg); err != nil {\n\t\t\t\tm.l.WithError(err).WithField(\"raw_config\", string(hookConfig.Config)).Error(\"failed to unmarshal hook configuration, ignoring hook\")\n\t\t\t\treturn nil, errors.WithStack(fmt.Errorf(\"failed to unmarshal webhook configuration for %s: %w\", credentialsType, err))\n\t\t\t}\n\t\t\tif h, ok := any(hook.NewWebHook(m, &cfg)).(T); ok {\n\t\t\t\thooks = append(hooks, h)\n\t\t\t}\n\t\tcase hook.KeyRequireVerifiedAddress:\n\t\t\tif h, ok := any(m.HookAddressVerifier()).(T); ok {\n\t\t\t\thooks = append(hooks, h)\n\t\t\t}\n\t\tcase hook.KeyVerificationUI:\n\t\t\tif h, ok := any(m.HookShowVerificationUI()).(T); ok {\n\t\t\t\thooks = append(hooks, h)\n\t\t\t}\n\t\tcase hook.KeyVerifier:\n\t\t\tif h, ok := any(m.HookVerifier()).(T); ok {\n\t\t\t\thooks = append(hooks, h)\n\t\t\t}\n\t\tcase hook.KeyVerifyNewAddress:\n\t\t\tif h, ok := any(m.HookVerifyNewAddress()).(T); ok {","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/ory/kratos/blob/b86338da04a040247a07f46100a86dcfb3875909/driver/registry_default_hooks.go#L70-L106","documentation":"getHooks builds the typed hook list for a credential lifecycle event. When a webhook hook's JSON config cannot be unmarshalled into request.Config, it logs the raw config and returns this wrapped error, aborting construction of the whole hook chain for that credentials type. The message names the credentials type and the underlying JSON error.","triggerScenarios":"A hook entry with key \"web_hook\" has a Config field that is not valid JSON for request.Config (e.g. malformed JSON, wrong top-level shape like an array or string, or a field with an incompatible type such as \"url\": 123).","commonSituations":"Typo in JSON config (trailing comma, single quotes); copying a YAML config into a JSON field; supplying the webhook URL as a number or object where a string is expected; renaming config keys after an Ory Kratos upgrade.","solutions":["Validate the hook's \"config\" JSON parses and matches request.Config (string \"url\", optional \"method\", \"body\", \"auth\" object with string fields)","Validate all JSON config files/DB rows with jq or a JSON linter before deploying","Check the logged raw_config field in the error log to see the exact offending bytes","Enable the hook via a config snippet known-good from the repo's test fixtures"],"exampleFix":"// before\n{\"hooks\": [{\"job\": \"web_hook\", \"config\": {\"url\": http://x, \"method\": \"POST\"}}]}\n// after\n{\"hooks\": [{\"job\": \"web_hook\", \"config\": {\"url\": \"http://x\", \"method\": \"POST\"}}]}","handlingStrategy":"validation","validationCode":"// Go: validate webhook hook config before registering\nfunc validWebHookConfig(raw json.RawMessage) error {\n\tvar cfg request.Config\n\tif err := json.Unmarshal(raw, &cfg); err != nil {\n\t\treturn fmt.Errorf(\"invalid web_hook config: %w\", err)\n\t}\n\treturn nil\n}","typeGuard":"func isWebHookConfigOK(raw json.RawMessage) bool {\n\tvar cfg request.Config\n\treturn len(raw) > 0 && json.Unmarshal(raw, &cfg) == nil\n}","tryCatchPattern":"hooks, err := reg.PostRegistrationPostPersistHooks(ctx, credentialsType)\nif err != nil {\n\tvar jsonErr *json.UnmarshalTypeError\n\tif errors.As(err, &jsonErr) {\n\t\tlog.Printf(\"fix web_hook config: field %s at offset %d\", jsonErr.Field, jsonErr.Offset)\n\t}\n\treturn err\n}","preventionTips":["Validate the whole Kratos config JSON against the schema at CI time","Run jq . over every JSON config block before applying changes","Keep webhook configs in linted config files, not hand-edited DB rows","Test hook registration in a staging environment before production rollout"],"tags":["json","configuration","webhook","unmarshal"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"b86338da04a040247a07f46100a86dcfb3875909","analyzedAt":"2026-09-07T15:58:15.934Z","contentChangedAt":"2026-09-07T15:58:15.934Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}