caddyserver/caddy · error

loading packet conn wrapper modules: %v

Error message

loading packet conn wrapper modules: %v

What it means

ctx.LoadModule instantiates servers.<name>.packet_conn_wrappers (modules implementing caddy.PacketConnWrapper, which wrap UDP/QUIC sockets before the QUIC handshake). Any unregistered module ID or failing Provision aborts app provisioning. There is no QUIC placeholder wrapper, unlike the TLS chain.

Source

Thrown at modules/caddyhttp/app.go:357

					}
					hasTLSPlaceholder = true
				}
				srv.listenerWrappers = append(srv.listenerWrappers, val.(caddy.ListenerWrapper))
			}
			// if any wrappers were configured but the TLS placeholder wrapper is
			// absent, prepend it so all defined wrappers come after the TLS
			// handshake; this simplifies logic when starting the server, since we
			// can simply assume the TLS placeholder will always be there
			if !hasTLSPlaceholder && len(srv.listenerWrappers) > 0 {
				srv.listenerWrappers = append([]caddy.ListenerWrapper{new(tlsPlaceholderWrapper)}, srv.listenerWrappers...)
			}
		}

		// set up each packet conn modifier
		if srv.PacketConnWrappersRaw != nil {
			vals, err := ctx.LoadModule(srv, "PacketConnWrappersRaw")
			if err != nil {
				return fmt.Errorf("loading packet conn wrapper modules: %v", err)
			}
			// if any wrappers were configured, they come before the QUIC handshake;
			// unlike TLS above, there is no QUIC placeholder
			for _, val := range vals.([]any) {
				srv.packetConnWrappers = append(srv.packetConnWrappers, val.(caddy.PacketConnWrapper))
			}
		}

		// pre-compile the primary handler chain, and be sure to wrap it in our
		// route handler so that important security checks are done, etc.
		primaryRoute := emptyHandler
		if srv.Routes != nil {
			err := srv.Routes.ProvisionHandlers(ctx, app.Metrics)
			if err != nil {
				return fmt.Errorf("server %s: setting up route handlers: %v", srvName, err)
			}
			primaryRoute = srv.Routes.Compile(emptyHandler)
		}

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Check the wrapped error for the module name or option at fault
  2. Build with the required plugin (xcaddy build --with ...) or drop the entry
  3. Confirm the module actually implements PacketConnWrapper, not ListenerWrapper
Defensive patterns

Strategy: validation

Validate before calling

// ensure the module is compiled in before load
out, _ := exec.Command("caddy", "list-modules").Output()
for _, w := range srvCfg.PacketConnWrappersRaw {
    id := gjson.GetBytes(w, "wrapper").String()
    if !strings.Contains(string(out), id) {
        return fmt.Errorf("packet conn wrapper %q missing from build", id)
    }
}

Prevention

When it happens

Trigger: A packet_conn_wrappers entry referencing a module not compiled into the binary, a typo'd module ID, or a wrapper whose own provisioning fails on its options.

Common situations: Using QUIC/HTTP/3 with a custom packet-filtering plugin that is missing from the build; copying configs between builds with different plugins.

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/3a09e979e8255539. Report an issue: GitHub.