projectdiscovery/katana · error
add edge: action cannot be nil
Error message
add edge: action cannot be nil
What it means
AddEdge in the crawl graph refuses to add an edge whose action attribute is nil, because the edge label is derived from action.String(). Passing a nil action is a programming error by the caller that builds the graph, not a runtime crawl condition.
Source
Thrown at pkg/engine/headless/graph/graph.go:87
}
err = g.graph.AddEdge(n.OriginID, n.UniqueID, func(ep *graph.EdgeProperties) {
ep.Weight = n.Depth
ep.Attributes = edgeAttrs
})
if err != nil {
if errors.Is(err, graph.ErrEdgeAlreadyExists) {
return nil
}
return errors.Wrapf(err, "could not add edge to graph: source vertex %s", n.OriginID)
}
}
return nil
}
func (g *CrawlGraph) AddEdge(sourceState, targetState string, action *types.Action) error {
if action == nil {
return errors.New("add edge: action cannot be nil")
}
edgeAttrs := map[string]string{
"label": action.String(),
}
err := g.graph.AddEdge(sourceState, targetState, func(ep *graph.EdgeProperties) {
ep.Weight = action.Depth
ep.Attributes = edgeAttrs
})
if err != nil {
if errors.Is(err, graph.ErrEdgeAlreadyExists) {
return nil
}
return errors.Wrap(err, "could not add edge to graph")
}
return nil
}
func (g *CrawlGraph) GetPageState(id string) (*types.PageState, error) {View on GitHub (pinned to e3e742739c)
Solutions
- Fix the caller to never pass a nil action; skip or default-initialize the action before AddEdge
- Guard call sites with if action == nil { continue } when iterating possibly-empty action slices
- Return and propagate the error instead of ignoring it when composing graph updates
Example fix
// before
graph.AddEdge(from, to, action) // panics-free but returns error ignored
// after
if action == nil {
return nil // skip states with no action
}
if err := graph.AddEdge(from, to, action); err != nil { return err } Defensive patterns
Strategy: validation
Validate before calling
func safeAddEdge(g *graph.CrawlGraph, from, to string, action *types.Action) error {
if action == nil { return nil }
return g.AddEdge(from, to, action)
} Type guard
func hasAction(a *types.Action) bool { return a != nil } Try / catch
if err := g.AddEdge(from, to, action); err != nil {
return fmt.Errorf("add edge %s->%s: %w", from, to, err)
} Prevention
- Never construct edges from uninitialized action pointers
- Skip nil actions when iterating optional action slices
- Check AddEdge's returned error instead of discarding it
When it happens
Trigger: Calling CrawlGraph.AddEdge(sourceState, targetState, nil) (graph.go:87) — typically when constructing graph edges from actions that were not properly initialized, or deserialized action structs that ended up nil.
Common situations: Custom code building/inspecting the crawl graph; recovering actions from serialized state where an action pointer is nil; test harnesses stubbing AddEdge with nil actions.
Related errors
AI-assisted analysis of projectdiscovery/katana@e3e742739c (2026-09-03).
Data as JSON: /api/errors/4d799237d60f855f.
Report an issue: GitHub.