{"record":{"id":"da5212f1abfaf714","repo":"ory/kratos","slug":"no-courier-channels-configured-for-s","errorCode":null,"errorMessage":"no courier channels configured for: %s","messagePattern":"no courier channels configured for: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"courier/courier_dispatcher.go","lineNumber":43,"sourceCode":"\tfor _, channel := range cs {\n\t\tif channel.ID != id {\n\t\t\tcontinue\n\t\t}\n\t\tswitch channel.Type {\n\t\tcase \"smtp\":\n\t\t\tcourierChannel, err := NewSMTPChannelWithCustomTemplates(c.deps, channel.SMTPConfig, c.newEmailTemplateFromMessage)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\treturn courierChannel, nil\n\t\tcase \"http\":\n\t\t\treturn newHttpChannel(channel.ID, &channel.RequestConfig, c.deps), nil\n\t\tdefault:\n\t\t\treturn nil, errors.Errorf(\"unknown courier channel type: %s\", channel.Type)\n\t\t}\n\t}\n\n\treturn nil, errors.Errorf(\"no courier channels configured for: %s\", id)\n}\n\nfunc (c *courier) DispatchMessage(ctx context.Context, msg Message) (err error) {\n\tctx, span := c.deps.Tracer(ctx).Tracer().Start(ctx, \"courier.DispatchMessage\", trace.WithAttributes(\n\t\tattribute.Stringer(\"message.id\", msg.ID),\n\t\tattribute.Stringer(\"message.nid\", msg.NID),\n\t\tattribute.Stringer(\"message.type\", msg.Type),\n\t\tattribute.String(\"message.template_type\", string(msg.TemplateType)),\n\t\tattribute.Int(\"message.send_count\", msg.SendCount),\n\t))\n\tdefer otelx.End(span, &err)\n\tctx = semconv.ContextWithAttributes(ctx, semconv.AttrNID(msg.NID))\n\n\tlogger := c.deps.Logger().\n\t\tWithField(\"message_id\", msg.ID).\n\t\tWithField(\"message_nid\", msg.NID).\n\t\tWithField(\"message_type\", msg.Type).\n\t\tWithField(\"message_template_type\", msg.TemplateType).","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/ory/kratos/blob/b86338da04a040247a07f46100a86dcfb3875909/courier/courier_dispatcher.go#L25-L61","documentation":"When DispatchMessage needs a channel, the channels method iterates configured courier channels looking for a matching ID. If none matches, it returns this error naming the requested channel ID. It means the message references a channel that is not present in the courier configuration.","triggerScenarios":"Dispatching a message whose channel/recipient configuration points to a channel ID that does not appear in the courier channels list in config (e.g. message stored for channel \"sms_provider\" while config only defines \"sms\").","commonSituations":"Renaming or removing a channel in config while old messages still reference the old ID, running with a minimal config that omits channels while templates specify them, or mismatched IDs between environments (staging vs prod config).","solutions":["Add the missing channel with the referenced ID to the courier.channels config.","Compare the message's channel ID in the courier_messages table with the IDs in your config.","Ensure the same courier config is used across environments or migrate queued messages accordingly.","Delete or reassign stale queued messages referencing removed channel IDs."],"exampleFix":"// before (config.yaml)\ncourier:\n  channels: []\n// after\ncourier:\n  channels:\n    - id: sms\n      type: http\n      request_config:\n        method: POST\n        url: https://sms-provider.example/send","handlingStrategy":"validation","validationCode":"configured := map[string]bool{}\nfor _, ch := range cfg.Courier.Channels { configured[ch.ID] = true }\nif !configured[messageChannelID] {\n    return fmt.Errorf(\"channel %q is not configured in courier.channels\", messageChannelID)\n}","typeGuard":"null","tryCatchPattern":"if err := courier.DispatchMessage(ctx, msg); err != nil {\n    if strings.Contains(err.Error(), \"no courier channels configured\") {\n        log.Printf(\"message %s references unconfigured channel: %v\", msg.ID, err)\n        // requeue, dead-letter, or fix config\n        return nil\n    }\n    return err\n}","preventionTips":["Keep courier channel IDs stable across config changes and environments","Search the courier_messages table for channel references before removing a channel","Sync courier config between staging and production before deploying"],"tags":["courier","config","channel","missing-resource"],"backgroundTag":"resource-not-found","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"}