{"record":{"id":"c4feffaa6cf1cd24","repo":"gohugoio/hugo","slug":"failed-to-create-resource-for-path-q-expected-a","errorCode":null,"errorMessage":"failed to create resource for path %q, expected a resource.Resource, got %T","messagePattern":"failed to create resource for path %q, expected a resource\\.Resource, got %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"resources/resource_spec.go","lineNumber":169,"sourceCode":"\tFileCaches    filecache.Caches\n\n\t// Assets used after the build is done.\n\t// This is shared between all sites.\n\t*PostBuildAssets\n}\n\ntype PostBuildAssets struct {\n\tPostProcessResources *maphelpers.ConcurrentMap[string, postpub.PostPublishedResource]\n\tJSConfigBuilder      *jsconfig.Builder\n}\n\nfunc (r *Spec) NewResourceWrapperFromResourceConfig(rc *pagemeta.ResourceConfig) (resource.Resource, error) {\n\tcontent := rc.Content\n\tswitch r := content.Value.(type) {\n\tcase resource.Resource:\n\t\treturn cloneWithMetadataFromResourceConfigIfNeeded(rc, r), nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"failed to create resource for path %q, expected a resource.Resource, got %T\", rc.PathInfo.Path(), content.Value)\n\t}\n}\n\n// NewResource creates a new Resource from the given ResourceSourceDescriptor.\nfunc (r *Spec) NewResource(rd ResourceSourceDescriptor) (resource.Resource, error) {\n\tif err := rd.init(r); err != nil {\n\t\treturn nil, err\n\t}\n\n\tdir, name := path.Split(rd.TargetPath)\n\tdir = paths.ToSlashPreserveLeading(dir)\n\tif dir == \"/\" {\n\t\tdir = \"\"\n\t}\n\trp := internal.ResourcePaths{\n\t\tFile:            name,\n\t\tDir:             dir,\n\t\tBaseDirTarget:   rd.BasePathTargetPath,","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/resources/resource_spec.go#L151-L187","documentation":"Returned by Spec.NewResourceWrapperFromResourceConfig when the ResourceConfig.Content.Value is not a resource.Resource. The function type-switches on content.Value expecting an already-constructed resource.Resource; any other concrete type falls into the default branch and is reported via %T. This is an internal contract violation in how a ResourceConfig is assembled, not normally user-facing.","triggerScenarios":"Internal code path constructs a *pagemeta.ResourceConfig whose Content.Value is set to a plain string, []byte, os.File, or a custom type instead of a resource.Resource, then calls NewResourceWrapperFromResourceConfig. Typically reached via page resource parsing or the resources.FromString pipeline when a downstream caller mis-wraps the content.","commonSituations":"A Hugo internal refactor or third-party module/hook that builds ResourceConfig objects and forgets to wrap raw content in a resource.ResourceLink / resource clone. End users almost never see this unless they are calling the resources package directly or hit a regression.","solutions":["If you are calling NewResourceWrapperFromResourceConfig directly, ensure rc.Content.Value is a resource.Resource (e.g. produced by Spec.NewResource or resources.NewPointerResource) before calling it.","If this surfaces from a normal build, file a Hugo issue with the stack trace and the offending rc.PathInfo; it indicates an internal contract break rather than a config mistake.","Upgrade Hugo to the latest release; this is frequently fixed by an upstream patch since it is an internal invariant."],"exampleFix":"// before\nrc := &pagemeta.ResourceConfig{PathInfo: pi}\nrc.Content.Value = []byte(rawBytes) // wrong type\n\n// after\nres, _ := spec.NewResource(descriptor) // returns resource.Resource\nrc.Content.Value = res","handlingStrategy":"type-guard","validationCode":"// Before constructing a ResourceConfig, assert the value type.\nfunc isResource(v any) bool {\n    _, ok := v.(resource.Resource)\n    return ok\n}\n\nif !isResource(rc.Content.Value) {\n    return fmt.Errorf(\"Content.Value must be resource.Resource, got %T\", rc.Content.Value)\n}","typeGuard":"// Go type guard for resource.Resource.\nfunc asResource(v any) (resource.Resource, bool) {\n    r, ok := v.(resource.Resource)\n    return r, ok\n}","tryCatchPattern":null,"preventionTips":["When building ResourceConfig programmatically, always wrap content via Spec.NewResource.","Add internal tests asserting NewResourceWrapperFromResourceConfig only receives resource.Resource values.","Treat this error as an upstream bug if encountered in a normal build; pin a known-good Hugo version."],"tags":["internal","resource","type-assertion","resourceconfig"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}