{"record":{"id":"0dbf0f15f8bef5d2","repo":"crowdsecurity/crowdsec","slug":"appsec-datasource-requires-a-hub-this-is-a-bug-p","errorCode":null,"errorMessage":"appsec datasource requires a hub. this is a bug, please report","messagePattern":"appsec datasource requires a hub\\. this is a bug, please report","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/acquisition/modules/appsec/config.go","lineNumber":189,"sourceCode":"\t\t\treturn nil, fmt.Errorf(\"unable to resolve appsec_config %q: %w\", entry, err)\n\t\t}\n\n\t\tfor _, name := range names {\n\t\t\tif _, ok := seen[name]; ok {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tseen[name] = struct{}{}\n\t\t\ttoLoad = append(toLoad, name)\n\t\t}\n\t}\n\n\treturn toLoad, nil\n}\n\nfunc (w *Source) Configure(ctx context.Context, yamlConfig []byte, logger *log.Entry, _ metrics.AcquisitionMetricsLevel) error {\n\tif w.hub == nil {\n\t\treturn errors.New(\"appsec datasource requires a hub. this is a bug, please report\")\n\t}\n\n\tif w.lapiClientConfig == nil {\n\t\treturn errors.New(\"appsec datasource requires a lapi client configuration. this is a bug, please report\")\n\t}\n\n\tif err := w.UnmarshalConfig(yamlConfig); err != nil {\n\t\treturn fmt.Errorf(\"unable to parse appsec configuration: %w\", err)\n\t}\n\n\tif w.lapiClientConfig.Credentials == nil {\n\t\treturn errors.New(\"missing lapi client credentials\")\n\t}\n\n\tw.lapiURL = fmt.Sprintf(\"%sv1/decisions/stream\", w.lapiClientConfig.Credentials.URL)\n\tw.AuthCache = NewAuthCache()\n\n\tw.logger = logger","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/acquisition/modules/appsec/config.go#L171-L207","documentation":"The appsec acquisition Source's Configure() requires the Source struct to have been pre-initialized with a hub (the crowdsort local hub used to load appsec configs) before it can run. Configure() explicitly rejects a nil hub as an internal invariant: the datasource factory must call ConfigureCommonState or equivalent setup that injects the hub before Configure is invoked. If you see this, the acquisition wiring (not your YAML) is at fault.","triggerScenarios":"Source.Configure() is called on an appsec Source whose hub field was never set, i.e. the code path that constructs the datasource skipped ConfigureCommonState/hub injection. The error message itself says 'this is a bug, please report', so it arises from internal wiring, not user config.","commonSituations":"Seen during plugin development or custom acquisition runners that build an appsec Source manually and call Configure directly; also seen in tests (TestExclusion, TestDiscoveryPolling, etc.) or in the http-source setup path when the LAPI-side hub state is missing.","solutions":["Report the bug to CrowdSec with logs and the acquisition config","If you are embedding the appsec datasource, ensure the Source is created through the normal datasource registry so the hub is injected before Configure() is called","Check you are running matching versions of crowdsec and the appsec plugin (a binary built from mismatched sources can skip initialization)"],"exampleFix":"// before (custom runner)\nsrc := &appsec.Source{}\nerr := src.Configure(ctx, yaml, logger, metrics)\n// after\nsrc := &appsec.Source{}\nif err := src.ConfigureCommonState(state); err != nil { return err } // sets hub, lapiClientConfig\nerr := src.Configure(ctx, yaml, logger, metrics)","handlingStrategy":"try-catch","validationCode":"if src.hub == nil { return fmt.Errorf(\"appsec source not initialized: hub missing\") }\nerr := src.Configure(ctx, yaml, logger, metricsLevel)","typeGuard":"func isUninitializedSourceErr(err error) bool { return err != nil && strings.Contains(err.Error(), \"requires a hub\") }","tryCatchPattern":"if err := src.Configure(ctx, cfg, logger, lvl); err != nil {\n    if isUninitializedSourceErr(err) { /* report bug / fix wiring */ }\n    return err\n}","preventionTips":["Always construct appsec Sources through the acquisition registry rather than manually","Call the common-state setup before Configure","Keep crowdsec and plugin binaries built from the same commit"],"tags":["appsec","acquisition","initialization","lapi"],"backgroundTag":"internal-invariant-violation","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}