{"record":{"id":"8c36d4ee483a8622","repo":"crowdsecurity/crowdsec","slug":"unable-to-read-file-s-w","errorCode":null,"errorMessage":"unable to read file %s : %w","messagePattern":"unable to read file (.+?) : %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/appsec/appsec.go","lineNumber":665,"sourceCode":"}\n\nfunc (wc *AppsecConfig) SetUpLogger() {\n\tif wc.LogLevel == nil {\n\t\tlvl := wc.Logger.Logger.GetLevel()\n\t\twc.LogLevel = &lvl\n\t}\n\n\t/* wc.Name is actually the datasource name.*/\n\twc.Logger = wc.Logger.Dup().WithField(\"name\", wc.Name)\n\twc.Logger.Logger.SetLevel(*wc.LogLevel)\n}\n\nfunc (wc *AppsecConfig) LoadByPath(file string) error {\n\twc.Logger.Debugf(\"loading config %s\", file)\n\n\tyamlFile, err := os.ReadFile(file)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to read file %s : %w\", file, err)\n\t}\n\n\t// as  LoadByPath can be called several time, we append rules/hooks, but override other options\n\tvar tmp AppsecConfig\n\n\terr = yaml.UnmarshalStrict(yamlFile, &tmp)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to parse yaml file %s : %w\", file, err)\n\t}\n\n\t// Normalize phase-scoped sections: merge rules, options, and variables_tracking\n\t// into flat fields. Hooks stay in the phase sections for Build() to compile separately.\n\ttmp.normalizePhaseScoped()\n\n\tif wc.Name == \"\" && tmp.Name != \"\" {\n\t\twc.Name = tmp.Name\n\t}\n","sourceCodeStart":647,"sourceCodeEnd":683,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/appsec/appsec.go#L647-L683","documentation":"AppsecConfig.LoadByPath reads the appsec config file from disk before parsing it. If os.ReadFile fails (missing file, permission denied, path is a directory), the read error is wrapped with the file path. LoadByPath is the entry point for loading appsec configs both from the hub and from arbitrary local paths, so this fires when the file cannot be opened at all.","triggerScenarios":"Calling LoadByPath(file) where the file does not exist, is unreadable due to permissions, or is a directory; hub Load() passing item.State.LocalPath for an item whose files were deleted or moved after install.","commonSituations":"Typos in the appsec config path in acquis or config; crowdsec running as a user without read permission on /etc/crowdsec/appsec-configs/*; hub item installed state out of sync with the filesystem (files deleted manually); container image missing the config directory.","solutions":["Check the file exists at the printed path and fix the path (ls the appsec-configs directory)","Fix file permissions/ownership so the crowdsec user can read it","Re-install the hub appsec config (cscli hub update / cscli appsec-configs install) if files were deleted","If mounting configs in a container, verify the volume mount maps the file into the container path"],"exampleFix":"// before\n/appsec/configs/rules.yaml  # path does not exist\n// after\n/appsec/configs/crowdsecurity/virtual-patching.yaml  # actual hub-installed path","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check paths and permissions after packaging","Reinstall hub items rather than moving files"],"tags":["appsec","filesystem","io"],"backgroundTag":"file-read-failed","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}