projectdiscovery/nuclei · error
%s is not a named struct type
Error message
%s is not a named struct type
What it means
The scraper looked up typeName in the package's scope, found it, but its Underlying() type is not *types.Struct. Scrape only supports named struct types: interfaces, maps, slices, basic types, signatures, and pointer/alias chains ending outside a struct are rejected here.
Source
Thrown at pkg/js/devtools/tsgen/scrape.go:39
// get package
pkg, ok := p.imports[pkgName]
if !ok {
return errkit.Newf("package %v for type %v not found", pkgName, typeName)
}
// get type
obj := pkg.Types.Scope().Lookup(baseTypeName)
if obj == nil {
return errkit.Newf("type %v not found in package %+v", typeName, pkg)
}
// Ensure the object is a type name
typeNameObj, ok := obj.(*types.TypeName)
if !ok {
return errkit.Newf("%v is not a type name", typeName)
}
// Ensure the type is a named struct type
namedStruct, ok := typeNameObj.Type().Underlying().(*types.Struct)
if !ok {
return fmt.Errorf("%s is not a named struct type", typeName)
}
// fmt.Printf("got named struct %v\n", namedStruct)
// Iterate over the struct fields
d := &ExtObject{
builtIn: make(map[string]string),
nested: map[string]map[string]*ExtObject{},
}
// fmt.Printf("fields %v\n", namedStruct.NumFields())
for i := 0; i < namedStruct.NumFields(); i++ {
field := namedStruct.Field(i)
fieldName := field.Name()
if field.Exported() {
recursiveScrapeType(nil, fieldName, field.Type(), d)
}
}
entityMap := make(map[string]Entity)
// convert ExtObject to EntityView on GitHub (pinned to 265b3a3dec)
Solutions
- Give the binding a concrete named struct instead: wrap the non-struct type in a struct (e.g. struct{ Items []Item })
- Keep non-struct helper types out of the scraped API surface (unexport them or move them out of the module dir)
- If the type genuinely must be exposed, extend the scraper to handle the kind — report an issue
Example fix
// before
type Permissions map[string]bool // scraped -> error
// after
type Permissions struct { Allow map[string]bool } Defensive patterns
Strategy: type-guard
Type guard
func isNamedStruct(pkg *types.Package, typeName string) bool {
obj := pkg.Scope().Lookup(typeName)
if obj == nil { return false }
tn, ok := obj.(*types.TypeName)
if !ok { return false }
_, ok = tn.Type().Underlying().(*types.Struct)
return ok
} Try / catch
In scraper code, check the guard above before scraping and skip non-struct types with a warning; as a lib author, catch the message at codegen time and restructure the offending type into a struct.
Prevention
- Avoid aliases to interfaces/maps/slices in scraped API surfaces
- Keep binding types as plain exported structs
- Extend or report the scraper when a non-struct type genuinely must be exposed
When it happens
Trigger: tsgen trying to scrape a type like type FS = fs.FS (alias), type Handler interface{...}, type List []Item, or type ID string — all reachable in scope but not structs.
Common situations: Binding APIs that expose idiomatic Go alias/interface types; generics instantiations; standard-library types aliased into a lib's surface.
Related errors
- could not scrape and create new object: %s
- could not create entity parser: %s
- could not parse entities: %s
- could not create template data: %v
- could not write go template: %v
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/d501388ccfc7628c.
Report an issue: GitHub.