sqshq/sampler · critical

panic(err)

Error message

panic(err)

What it means

AudioPlayer.Beep panics if constructing the mp3.Decoder from the embedded beep asset fails — the bundled MP3 bytes cannot be parsed (truncated, wrong format, or corrupt embedded asset). This is a hard panic by design because a failed beep indicates a broken build embedding of assets.

Source

Thrown at asset/player.go:41

	if err != nil {
		// it is expected to fail when some of the system
		// libraries are not available (e.g. libasound2)
		// it is not the main functionality of the application,
		// so we allow startup in no-sound mode
		return nil
	}

	return &AudioPlayer{
		player: player,
		beep:   bytes,
	}
}

func (a *AudioPlayer) Beep() {

	decoder, err := mp3.NewDecoder(NewAssetFile(a.beep))
	if err != nil {
		panic(err)
	}

	if _, err := io.Copy(a.player, decoder); err != nil {
		panic(err)
	}
}

func (a *AudioPlayer) Close() {
	_ = a.player.Close()
}

View on GitHub (pinned to 9bc7ba732d)

Solutions

  1. Restore the original, valid MP3 asset and rebuild (verify go:embed includes the file)
  2. Regenerate/re-embed the beep asset and confirm mp3.NewDecoder succeeds in a unit test
  3. Wrap Beep with recover() if a missing sound should not crash the app, and log instead of panicking
  4. Verify the binary actually embeds assets (rebuild without -trimpath tricks that might affect embed paths)

Example fix

// before
func (a *AudioPlayer) Beep() {
    decoder, err := mp3.NewDecoder(NewAssetFile(a.beep))
    if err != nil {
        panic(err)
    }
// after
func (a *AudioPlayer) Beep() (err error) {
    defer func() { if r := recover(); r != nil { err = fmt.Errorf("beep failed: %v", r) } }()
    decoder, derr := mp3.NewDecoder(NewAssetFile(a.beep))
    if derr != nil { return derr }
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-validate embedded asset
f, err := asset.Asset("beep.mp3")
if err != nil || len(f) < 4 { audioDisabled = true }

Type guard

func audioAvailable() bool { data, err := asset.Asset("beep.mp3"); return err == nil && len(data) > 0 }

Try / catch

func safeBeep(p *asset.AudioPlayer) {
    defer func() { if r := recover(); r != nil { log.Printf("beep skipped: %v", r) } }()
    p.Beep()
}

Prevention

When it happens

Trigger: Calling Execute (which calls Beep) when NewAssetFile(a.beep) yields data that mp3.NewDecoder rejects — e.g. asset embedding changed, file replaced with non-MP3 content, or empty asset.

Common situations: Custom builds where go:embed assets were modified or regenerated incorrectly; stripped binaries missing embedded assets; corrupted resource after bundling/packing.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of sqshq/sampler@9bc7ba732d (2026-09-06). Data as JSON: /api/errors/38d4a20b39b3dbaa. Report an issue: GitHub.