Skip to content

fix: replace panic with proper error handling in catalog loader#7023

Open
Pitrat-wav wants to merge 2 commits intoprojectdiscovery:devfrom
Pitrat-wav:fix/replace-panic
Open

fix: replace panic with proper error handling in catalog loader#7023
Pitrat-wav wants to merge 2 commits intoprojectdiscovery:devfrom
Pitrat-wav:fix/replace-panic

Conversation

@Pitrat-wav
Copy link

@Pitrat-wav Pitrat-wav commented Feb 24, 2026

Proposed changes

This PR replaces panic statements with proper error handling in the catalog loader package and related code.

Changes

  • Changed Load() and LoadTemplates() functions to return errors instead of panicking
  • Replaced panic statements in LoadTemplatesWithTags with proper error returns
  • Updated all callers (runner, SDK, automaticscan) to handle the new error returns
  • Fixed a compilation error in internal/runner/lazy.go (variable redeclaration)
  • Updated benchmark tests to handle new error return values

Proof

  • Code compiles successfully with Go 1.23.5
  • All tests pass in pkg/catalog/loader and internal/runner

Checklist

  • Pull request is created against the dev branch
  • All checks passed (lint, unit/integration/regression tests etc.) with my changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

Fixes #6674

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Enhanced error handling throughout template loading operations for improved reliability.
    • System now properly detects failures during template initialization and halts instead of continuing silently.
    • Better error diagnostics when template loading encounters issues, enabling faster problem identification.

- Change Load() and LoadTemplates() to return errors instead of panicking
- Handle errors properly in runner, SDK, and automaticscan packages
- Fix compilation error in lazy.go (variable redeclaration)
- Update benchmark tests to handle new error return values

Fixes: projectdiscovery#6674

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@auto-assign auto-assign bot requested a review from Mzack9999 February 24, 2026 21:02
@neo-by-projectdiscovery-dev
Copy link

neo-by-projectdiscovery-dev bot commented Feb 24, 2026

Neo - PR Security Review

No security issues found

Highlights

  • Replaces panic statements with proper error handling in catalog loader
  • Updates all callers (runner, SDK, automaticscan) to handle new error returns
  • Fixes compilation error in internal/runner/lazy.go (variable redeclaration)
  • Updates benchmark tests to handle new error return values

Comment @neo help for available commands. · Open in Neo

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 24, 2026

Walkthrough

The pull request adds comprehensive error handling to template loading operations across the codebase. The Load(), LoadTemplates(), and LoadTemplatesWithTags() methods now return errors instead of panicking. All callers have been systematically updated to capture and propagate these errors, enabling graceful failure handling instead of silent failures.

Changes

Cohort / File(s) Summary
Loader Core Implementation
pkg/catalog/loader/loader.go
Updated Load(), LoadTemplates(), and LoadTemplatesWithTags() method signatures to return error alongside their primary return values. Replaced panic when dialers are missing with proper error returns, propagating errors from internal loading operations.
Caller Error Propagation
cmd/integration-test/library.go, internal/runner/runner.go, internal/server/nuclei_sdk.go, lib/multi.go, lib/sdk.go
Updated function implementations to capture error returns from store.Load() calls and propagate them upward, enabling fail-fast behavior on loader initialization failures.
Lazy Loading Error Handling
internal/runner/lazy.go
Added error handling for LoadTemplates() call within GetLazyAuthFetchCallback(). Preserved existing template validation logic and adjusted variable assignment pattern for error captures.
Automatic Scanning Utilities
pkg/protocols/common/automaticscan/util.go
Added error propagation from LoadTemplatesWithTags() return value to handle load failures in automatic technology detection workflows.
Benchmark Tests
pkg/catalog/loader/loader_bench_test.go
Updated benchmark tests to capture error returns from LoadTemplates() and LoadTemplatesOnlyMetadata() calls, using b.Fatal() to surface errors instead of silently ignoring them. Added b.Helper() calls for improved benchmark accuracy.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 Errors now surface with graceful care,
No more panics hiding in the air,
Templates load with proper flow,
Dialers checked before we go,
A safer path for every thread!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title accurately summarizes the main change: replacing panic statements with proper error handling in the catalog loader package.
Linked Issues check ✅ Passed All coding requirements from issue #6674 are met: panic replaced with error returns in LoadTemplatesWithTags, loader function signatures updated to propagate errors, and all callers updated to handle new error returns.
Out of Scope Changes check ✅ Passed All changes are within scope: error handling additions to loader functions and their callers, plus benchmark test updates to handle new error returns. No unrelated changes detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
REQUIREMENTS.md (1)

1-14: Same concern as STATE.md — this project-management artifact should not be committed.

See the comment on STATE.md.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@REQUIREMENTS.md` around lines 1 - 14, REQUIREMENTS.md is a project-management
artifact that shouldn't be committed (same issue as STATE.md); remove it from
the PR by deleting or moving it out of source control and update the commit set
(e.g., remove the file from the branch or add it to .gitignore/private docs),
then amend/rebase or create a new commit that removes REQUIREMENTS.md (and
ensure STATE.md is handled the same way); confirm the PR no longer contains
REQUIREMENTS.md and run a quick build/tests to ensure no code references the
file remain.
task.md (1)

1-12: Same concern as STATE.md — this project-management artifact should not be committed.

See the comment on STATE.md.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@task.md` around lines 1 - 12, This project-management artifact (task.md)
should not be committed; remove task.md from the commit (or delete it from the
repo), revert the addition if already committed, and add the filenames like
task.md and STATE.md to the repository ignore list (e.g., .gitignore or
.git/info/exclude) so they remain local only; ensure any CI/PR contents no
longer reference task.md and amend the PR to remove this file before final
submission.
🧹 Nitpick comments (2)
cmd/integration-test/library.go (1)

135-137: LGTM — error from store.Load() is now properly propagated.

Minor style note: other error returns in this function use errors.Wrap (e.g., lines 100 and 133), but this one is returned raw. Consider wrapping for consistency:

♻️ Optional: wrap the error for consistency
-	if err := store.Load(); err != nil {
-		return nil, err
-	}
+	if err := store.Load(); err != nil {
+		return nil, errors.Wrap(err, "could not load templates")
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/integration-test/library.go` around lines 135 - 137, The return of the
raw error from store.Load() should be wrapped for consistency with other error
returns; change the error return in the block around store.Load() to wrap the
error using errors.Wrap (or the same wrapping helper used elsewhere in this
file) and include context like "loading store" so it matches the style of the
other returns (see the existing errors.Wrap usages near library.go around the
earlier returns).
pkg/catalog/loader/loader_bench_test.go (1)

74-74: Consider checking the error return in benchmarks to avoid silently benchmarking failure paths.

All benchmark loops discard the error from LoadTemplates. If the setup is ever misconfigured (e.g., missing protocolstate initialization — the exact scenario this PR fixes), benchmarks will silently measure error-return performance instead of actual template loading.

A lightweight guard like b.Helper(); if err != nil { b.Fatal(err) } on the first iteration would catch this.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/catalog/loader/loader_bench_test.go` at line 74, The benchmark loop
discards the error returned by store.LoadTemplates which can hide setup
failures; modify the benchmark (the function calling store.LoadTemplates) to
check the error on the first iteration by calling b.Helper() and if err != nil
call b.Fatal(err) (or b.Fatalf) so the benchmark fails fast instead of measuring
error paths; reference the call to store.LoadTemplates / LoadTemplates and the
b.Fatal/b.Helper helpers to locate where to add the guard.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@implementation_plan.md`:
- Around line 8-12: Remove the developer-local absolute URIs from
implementation_plan.md: replace the file:///home/... entries referencing lazy.go
and automaticscan.go with neutral identifiers (just the filenames or
project-relative paths) or remove the tracking lines entirely so no local
username or tooling paths are present; ensure the modified entries refer only to
lazy.go and automaticscan.go (or a relative repo path) and do not include any
absolute local filesystem URIs, and avoid committing state/tracking files that
contain such paths.

In `@STATE.md`:
- Around line 1-15: Remove the personal project-tracking files (STATE.md,
REQUIREMENTS.md, task.md, implementation_plan.md) from the PR by deleting them
from the repository or staging them for removal; if you still need them locally,
add them to .gitignore and remove them from the index (e.g., stop tracking with
git rm --cached) so they aren't committed, update the PR to reflect the
deletions, and ensure no code references these filenames (STATE.md is shown in
the diff) before pushing the updated commit.

---

Duplicate comments:
In `@REQUIREMENTS.md`:
- Around line 1-14: REQUIREMENTS.md is a project-management artifact that
shouldn't be committed (same issue as STATE.md); remove it from the PR by
deleting or moving it out of source control and update the commit set (e.g.,
remove the file from the branch or add it to .gitignore/private docs), then
amend/rebase or create a new commit that removes REQUIREMENTS.md (and ensure
STATE.md is handled the same way); confirm the PR no longer contains
REQUIREMENTS.md and run a quick build/tests to ensure no code references the
file remain.

In `@task.md`:
- Around line 1-12: This project-management artifact (task.md) should not be
committed; remove task.md from the commit (or delete it from the repo), revert
the addition if already committed, and add the filenames like task.md and
STATE.md to the repository ignore list (e.g., .gitignore or .git/info/exclude)
so they remain local only; ensure any CI/PR contents no longer reference task.md
and amend the PR to remove this file before final submission.

---

Nitpick comments:
In `@cmd/integration-test/library.go`:
- Around line 135-137: The return of the raw error from store.Load() should be
wrapped for consistency with other error returns; change the error return in the
block around store.Load() to wrap the error using errors.Wrap (or the same
wrapping helper used elsewhere in this file) and include context like "loading
store" so it matches the style of the other returns (see the existing
errors.Wrap usages near library.go around the earlier returns).

In `@pkg/catalog/loader/loader_bench_test.go`:
- Line 74: The benchmark loop discards the error returned by store.LoadTemplates
which can hide setup failures; modify the benchmark (the function calling
store.LoadTemplates) to check the error on the first iteration by calling
b.Helper() and if err != nil call b.Fatal(err) (or b.Fatalf) so the benchmark
fails fast instead of measuring error paths; reference the call to
store.LoadTemplates / LoadTemplates and the b.Fatal/b.Helper helpers to locate
where to add the guard.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d771daa and 507a383.

📒 Files selected for processing (15)
  • PROJECT.md
  • REQUIREMENTS.md
  • ROADMAP.md
  • STATE.md
  • cmd/integration-test/library.go
  • implementation_plan.md
  • internal/runner/lazy.go
  • internal/runner/runner.go
  • internal/server/nuclei_sdk.go
  • lib/multi.go
  • lib/sdk.go
  • pkg/catalog/loader/loader.go
  • pkg/catalog/loader/loader_bench_test.go
  • pkg/protocols/common/automaticscan/util.go
  • task.md

STATE.md Outdated
Comment on lines 1 to 15
# State - Nuclei Panic Fix

## Current Phase
Phase 1: Core Loader Modification

## Status
- Project Initialized
- Vibe Kanban Sync: Done
- Codebase Mapped: Done (Found panics at lines 711, 720)

## Blockers
None

## Decision Log
- 2026-02-25: Decided to focus on error propagation instead of just removing panic to ensure robust error handling.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove project-tracking files from the repository.

STATE.md, along with REQUIREMENTS.md, task.md, and implementation_plan.md, appear to be personal/AI-agent project-management artifacts rather than project documentation. They should not be committed to the repository — they add noise for other contributors and will go stale immediately.

Consider adding them to .gitignore or removing them from this PR entirely.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@STATE.md` around lines 1 - 15, Remove the personal project-tracking files
(STATE.md, REQUIREMENTS.md, task.md, implementation_plan.md) from the PR by
deleting them from the repository or staging them for removal; if you still need
them locally, add them to .gitignore and remove them from the index (e.g., stop
tracking with git rm --cached) so they aren't committed, update the PR to
reflect the deletions, and ensure no code references these filenames (STATE.md
is shown in the diff) before pushing the updated commit.

- Remove GSD project management files from git index (keep locally)
- Add error checking in benchmark loops with b.Helper() guard
- Wrap raw error from store.Load() with proper context

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/catalog/loader/loader_bench_test.go (1)

240-252: ⚠️ Potential issue | 🟡 Minor

Pre-warm call silently ignores errors.

LoadTemplatesOnlyMetadata() now returns an error per this PR. Ignoring the pre-warm error with _ = means a failure here goes undiagnosed; the benchmark will only surface the error on the first timed iteration (inside the loop), with no indication that the failure originated during warm-up. Use b.Fatal on the pre-warm call too for clearer diagnostics.

🛡️ Proposed fix
-		// Pre-warm the cache
-		_ = store.LoadTemplatesOnlyMetadata()
+		// Pre-warm the cache
+		if err := store.LoadTemplatesOnlyMetadata(); err != nil {
+			b.Fatalf("pre-warm failed: %s", err)
+		}

Apply the same fix to the WithSeverityFilter sub-benchmark (line 266).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/catalog/loader/loader_bench_test.go` around lines 240 - 252, The pre-warm
call currently ignores errors by assigning `_ =
store.LoadTemplatesOnlyMetadata()`: change this to call
store.LoadTemplatesOnlyMetadata() and if it returns an error call b.Fatal(err)
so warm-up failures are reported immediately; apply the same change to the
WithSeverityFilter sub-benchmark pre-warm so both pre-warm invocations of
LoadTemplatesOnlyMetadata() use b.Fatal on error (referencing the store variable
and the LoadTemplatesOnlyMetadata function).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/catalog/loader/loader_bench_test.go`:
- Around line 73-79: Move the b.Helper() call out of the timed benchmark loop so
it doesn't skew measurements: remove b.Helper() from inside each for b.Loop()
block and place a single b.Helper() call immediately before entering the loop
(or at the top of the sub-benchmark closure) for each benchmark that calls
store.LoadTemplates (and similar loops), ensuring only the body that should be
measured (e.g., _, err := store.LoadTemplates(...); if err != nil { b.Fatal(err)
}) remains inside for b.Loop().

---

Outside diff comments:
In `@pkg/catalog/loader/loader_bench_test.go`:
- Around line 240-252: The pre-warm call currently ignores errors by assigning
`_ = store.LoadTemplatesOnlyMetadata()`: change this to call
store.LoadTemplatesOnlyMetadata() and if it returns an error call b.Fatal(err)
so warm-up failures are reported immediately; apply the same change to the
WithSeverityFilter sub-benchmark pre-warm so both pre-warm invocations of
LoadTemplatesOnlyMetadata() use b.Fatal on error (referencing the store variable
and the LoadTemplatesOnlyMetadata function).

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 507a383 and ce12011.

📒 Files selected for processing (2)
  • cmd/integration-test/library.go
  • pkg/catalog/loader/loader_bench_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmd/integration-test/library.go

Comment on lines 73 to 79
for b.Loop() {
_ = store.LoadTemplates([]string{config.DefaultConfig.TemplatesDirectory})
b.Helper()
_, err := store.LoadTemplates([]string{config.DefaultConfig.TemplatesDirectory})
if err != nil {
b.Fatal(err)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Move b.Helper() out of the benchmark loop — it pollutes measurement.

b.Helper() should be called once at the top of the function body (or sub-benchmark closure), not inside the for b.Loop() body. Every statement between the braces of a b.Loop() loop is timed; calling b.Helper() on each iteration adds overhead that skews the benchmark results. While the effect is idempotent on the helper registration, the function call itself executes every iteration.

♻️ Proposed fix (representative example — same pattern for all sub-benchmarks)
 	b.Run("NoFilter", func(b *testing.B) {
+		b.Helper()
 		loaderCfg := loader.NewConfig(options, catalog, executerOpts)
 		store, err := loader.New(loaderCfg)
 		if err != nil {
 			b.Fatalf("could not create store: %s", err)
 		}

 		b.ResetTimer()
 		b.ReportAllocs()

 		for b.Loop() {
-			b.Helper()
 			_, err := store.LoadTemplates([]string{config.DefaultConfig.TemplatesDirectory})
 			if err != nil {
 				b.Fatal(err)
 			}
 		}
 	})

Also applies to: 95-101, 117-123, 139-145, 161-167, 183-189, 207-213, 246-252, 271-277

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/catalog/loader/loader_bench_test.go` around lines 73 - 79, Move the
b.Helper() call out of the timed benchmark loop so it doesn't skew measurements:
remove b.Helper() from inside each for b.Loop() block and place a single
b.Helper() call immediately before entering the loop (or at the top of the
sub-benchmark closure) for each benchmark that calls store.LoadTemplates (and
similar loops), ensuring only the body that should be measured (e.g., _, err :=
store.LoadTemplates(...); if err != nil { b.Fatal(err) }) remains inside for
b.Loop().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace panic with error handling in template loader when dialers are missing

1 participant