zoobzio December 29, 2025 3 mins Edit this page

Troubleshooting

Common issues when using sentinel and how to resolve them.

Panic on Inspect or Scan

Symptom: panic: sentinel: type must be a struct

Cause: You passed a non-struct type to Inspect[T]() or Scan[T]().

Solution: Use the Try variants which return an error instead of panicking:

metadata, err := sentinel.TryInspect[MyType]()
if err != nil {
    // Handle non-struct type
}

Custom Tags Not Appearing

Symptom: Your custom tag is missing from field.Tags.

Cause: Tags were registered after the type was already extracted and cached.

Solution: Register tags before the first Inspect or Scan call:

// Do this first
sentinel.Tag("custom")

// Then extract
metadata := sentinel.Inspect[User]()

If the type is already cached, the original extraction (without your tag) will be returned. In tests, use sentineltest.ResetCache(t) to clear the cache.

Types Not Discovered by Scan

Symptom: Related types are missing from the cache after Scan.

Cause: The types are outside your module boundary.

Solution: Scan only recurses into types within your module (determined by go.mod). Types from external packages are recorded as relationships but not extracted.

// Your module: github.com/you/app

type User struct {
    Profile  Profile       // ✓ Extracted (same module)
    Created  time.Time     // ✗ Not extracted (stdlib)
    NullName sql.NullString // ✗ Not extracted (external)
}

If you need metadata for external types, use Inspect explicitly:

sentinel.Inspect[sql.NullString]()

Scan Not Recursing

Symptom: Scan behaves like Inspect—only the root type is cached.

Cause: Module path detection failed. This happens when debug.ReadBuildInfo() returns no data.

When this occurs:

  • Running with go run outside a module
  • Some build configurations that strip debug info

Solution: Ensure you're running within a Go module context, or use Inspect explicitly for each type you need.

Unexported Fields Missing

Symptom: Some struct fields don't appear in metadata.Fields.

Cause: Only exported fields (uppercase names) are included. Go's reflection cannot access unexported fields from outside their package.

type User struct {
    ID   string // ✓ Included
    name string // ✗ Not included (unexported)
}

Solution: This is expected behaviour. Export fields you need metadata for.

Stale Cache in Tests

Symptom: Test assertions fail because metadata reflects a previous extraction.

Cause: Sentinel's cache persists across tests.

Solution: Use the testing helpers with -tags testing:

func TestSomething(t *testing.T) {
    sentineltest.ResetCache(t)
    // Fresh extraction
}

Run with: go test -tags testing ./...

Next Steps