Skip to content
GopherTrunk
    • What is GopherTrunk?
    • Get started
    • Basics
    • Intermediate
    • Advanced
    • All learning
    • Path: RF Software Development
    • Path: RF Hardware
    • Path: Software Engineering
    • Path: AI Software Development
    • Path: Cybersecurity
    • Path: Digital Trunking & Scanning
    • Module: RF & SDR
    • Module: Git & GitHub
    • Module: Intro to Software Dev
    • Module: Digital Trunking
    • Module: Intro to Hardware
    • Module: Programming in Go
    • Module: Digital Signal Processing
    • Module: Containers & Deployment
    • Module: Databases & Data
    • Module: Web Development
    • Module: Scanning & Monitoring
    • Module: Testing & Software Quality
    • Module: APIs & Protocols
    • Module: Embedded & Single-Board Computers
    • Field Guide overview
    • RF & SDR
    • RF & signal fundamentals
    • Modulation
    • SDR & DSP
    • Algorithms
    • Cryptography & cryptanalysis
    • Trunked radio
    • Protocols & standards
    • Voice coding
    • Hardware
    • People
    • Organizations
    • Software Development
    • Programming languages
    • Language internals & execution
    • Concurrency & execution models
    • Paradigms & design patterns
    • Principles & code quality
    • Testing, tooling & delivery
    • Hardware (computers & devices)
    • Hardware foundations
    • Servers & hosting
    • Personal computers
    • Mobile devices
    • Single-board computers
    • Microcontrollers
    • Networking & connectivity
    • Storage & memory
    • GPUs, FPGAs & accelerators
    • People
    • Organizations & makers
    • Field Notes
    • Hardware quirks
    • Configuration gotchas
    • Diagnostic signatures & playbook
    • Protocol facts the specs hide
    • The Story of GopherTrunk
    • Forum
    • Account
    • Profile
    • Moderation
    • All posts
    • Announcements
    • Releases
    • Deep dives
    • Series: SDR Internals
    • Series: RF Front End
    • Series: Trunking Engine
    • Series: Protocol Decoders
    • Series: Voice Coding
    • Series: Recording, Composition & Streaming
    • Series: The Hunt
    • Series: The Operator's Cockpit
    • Series: Running It For Real
    • Series: TETRA End to End
    • Series: Weak-Signal Engineering
    • Series: P25 End to End
    • Series: From Spec to Shipping
    • Series: DMR End to End
    • Series: Beyond Voice
    • Tutorials
    • Series: Signal Lab
    • Series: RF Scope
    • Series: Crypto Lab
    • Series: The Analog Edge
    • Series: The Operator's Cookbook
    • Series: The Field Notebook
    • Solution Postmortem
    • Series: From the Issue Tracker
    • Start here
    • What hardware do I need?
    • Police scanner vs GopherTrunk (SDR)
    • Build lists
    • All GopherTrunk build lists
    • PC / laptop build
    • Raspberry Pi / SBC build
    • Outdoor base station build
    • Portable / field build
    • Multi-dongle build
    • Police scanners
    • Best police scanners
    • How police scanners work
    • Scanner encryption explained
    • Is a police scanner legal?
    • Scanner frequencies by service
    • How to program a scanner
    • All scanner models (Field Guide)
    • Ham radios
    • Best base stations
    • Best mobile ham radios
    • Best handheld ham radios
    • All ham radios (Field Guide)
    • Two-way radios
    • Best walkie-talkies
    • Best GMRS mobile radios
    • Best CB radios
    • All two-way radios (Field Guide)
    • Shortwave & emergency
    • Best shortwave radios
    • Best emergency radios
    • Best desktop shortwave receivers
    • All shortwave radios (Field Guide)
    • SDRs & receivers
    • Best SDR for GopherTrunk
    • Best RTL-SDR
    • Best HF SDR
    • All SDR devices (Field Guide)
    • Antennas & accessories
    • Best scanner antennas
    • Best SDR antenna
    • SDR cables & connectors
    • Masts, mounts & mounting hardware
    • LNAs & filters
    • Computers
    • Best single-board computer
    • Run GopherTrunk on a Raspberry Pi
    • All SBCs (Field Guide)
    • Setup
    • SDR hardware setup
    • Downloads
    • Hardware
    • Linux install
    • macOS install
    • Windows install
    • Launcher
    • Windows user guide
    • TUI
    • Web console
    • Live edits
    • Import (PDF / CSV)
    • Bookmarks
    • CC Activity
    • Radio IDs
    • Plots (signal scopes)
    • Constellation
    • Symbol scope
    • Eye diagram
    • Tuning (receiver meters)
    • Symbol histogram
    • Hunt (discover systems)
    • SigLab (offline workbench)
    • RF Scope (protocol-agnostic scene analysis)
    • rigctld integration
    • Event API & webhooks
    • Hardening
    • Architecture
    • Vocoders
    • Voice calibration
    • DMR encryption
    • POCSAG paging
    • APRS / AX.25
    • Opt-in features
    • Status
    • Roadmap
    • Cutting a release
    • Support
  • Account
  1. Home
  2. Blog
  3. Blog: Solution Postmortem
  • From the Issue Tracker, Part 22: Two Pipelines, One Symptom — When Parallel Code Paths Drift

    September 3, 2026

    GopherTrunk grew parallel implementations of the same contract — daemon vs replay, single-channel vs wideband, C4FM vs CQPSK — and five issues trace to one path getting a fix, a warning, or a config knob the other never received. The series finale, with the rules that keep twins honest.

  • From the Issue Tracker, Part 21: Census Everything — The Silence of a Success-Only Log Line Carries No Information

    September 2, 2026

    Five GopherTrunk investigations stalled or went sideways because the logs only spoke on success — zero lines from a dead decoder looks identical at every failure stage. The fix each time was a census — an unconditional per-unit count with denominators — and this post distills when and how to add one.

  • From the Issue Tracker, Part 20: The Self-Consistent Trap — Round-Trip Tests That Validate Their Own Bugs

    September 1, 2026

    Seven GopherTrunk bugs shipped behind green test suites because the encoder and decoder shared the same wrong constant, table, or convention — a wrong sync word, a wrong BCH polynomial, a skipped descramble — and a round-trip test cannot see a mistake it makes twice.

  • From the Issue Tracker, Part 19: One Render Loop — A Blank UI, a Host-less URL, and React Error #185

    August 31, 2026

    A blank web UI, a WebSocket URL missing its host, sockets closing before the handshake, and React's maximum-update-depth error all traced to a single unstable selector in an effect dependency array — plus a separate go:embed trap that shipped a binary whose web assets were one .gitkeep file.

  • From the Issue Tracker, Part 18: The Stall That Wasn't — A Dongle Off the Bus and an Opcode Off the Books

    August 30, 2026

    A decoder that "stalled" after a clean control-channel lock turned out to be a dongle leaving the USB bus, a retry loop that matched only one error sentinel and left the daemon half-dead, and — found by running p25_survey as an oracle — a TDMA IDEN_UP opcode the dispatcher never handled.

  • From the Issue Tracker, Part 17: Placeholder Constants — The TETRA Sync That Never Existed

    August 29, 2026

    TETRA never locked because the training-sequence constants were placeholders — 76 bits declared into a 64-bit variable, bits conflated with dibits, and a linear dibit mapping where the air uses Gray — and every test passed because the fixtures were built from the same wrong constants.

  • From the Issue Tracker, Part 16: The Channel That Was Its Own Voice Channel — Conventional FM and the IQ Broker

    August 28, 2026

    Conventional analog FM channels lit up with activity and recorded nothing. Fixing the composer's digital-only gate revealed a second bug hiding behind it — in conventional scanning the monitored channel is the recorded channel, and a single-consumer device API can't serve both.

  • From the Issue Tracker, Part 15: The Silent MP3 — Three Encoder Bugs and a Test That Checked One Frame

    August 27, 2026

    Rdio Scanner accepted every upload and played silence. Behind it sat three independent MP3 encoder bugs — an illegal bitrate corrupting headers via putBits(-1), bit-reservoir stuffing desync, and a mono stride that skipped half the audio — none caught by a test that only checked the first frame's sync word.

  • From the Issue Tracker, Part 14: The Recorder Is the Decoder — Perfect Recordings, Silent Speakers

    August 26, 2026

    Live audio in the web UI did nothing while recordings came out flawless. Two plausible fixes shipped before a 44-byte curl probe exposed the real cause — only the recorder ever decoded vocoder frames to PCM, so every live path was silently skipped.

  • From the Issue Tracker, Part 13: The SoapyRemote Handshake — Three Wrong Root Causes and a Server That Says Nothing First

    August 25, 2026

    A SoapySDRServer fronting a USRP X310 segfaulted the moment GopherTrunk connected. The reporter filed three confident root-cause analyses; all three were disproved by the code. The real bugs were a two-phase, two-socket SETUP_STREAM handshake the client half-implemented — and a TCP flow-control ACK without which the server sends zero samples, forever.

  • From the Issue Tracker, Part 12: Seventy-Eight Degrees — The Phase Angle That Named the Bug

    August 24, 2026

    An Airspy R2 that refused to open because its opcode table was systematically shifted, then opened and decoded nothing at all. One diagnostic triplet — EVM 22.7%, phase imbalance +78.1°, image rejection 3.3 dB — read as a sentence, named the bug: a real-sampling stream misread as interleaved I/Q.

  • From the Issue Tracker, Part 11: Detected but Not Present — One Hex Code from a Fix That Already Existed

    August 23, 2026

    macOS enumerated the dongle, then the daemon insisted the configured SDR wasn't on the bus. One probe line surfaced IOKit kern_return 0xe000404f — a pipe stall GopherTrunk already knew how to recover from on Linux and Windows, except the macOS backend never translated the error.

  • From the Issue Tracker, Part 10: Faster Than libusb — When the Second Write Outruns the First

    August 22, 2026

    A Windows 10 dongle accepted a control write and then rejected its byte-identical twin with ERROR_GEN_FAILURE. The retry-envelope fix couldn't work by construction — the real bug was that a pure-Go WinUSB path is thinner than libusb's stack, and libusb's overhead had been hiding a firmware race.

  • From the Issue Tracker, Part 9: Broken Pipe — Six Rounds of Traces for One USB Write

    August 21, 2026

    Two NESDR SMArt v5 dongles that worked in every other SDR app failed GopherTrunk's tuner init with one EPIPE. Five parity fixes didn't take, one of them shipped a regression of our own making, and paired USB traces ruled out everything until a 5 ms sleep closed it.

  • From the Issue Tracker, Part 8: Nineteen Dibits — A Perfect Hypothesis Meets a Rail-Pinned ADC

    August 20, 2026

    A meticulously argued bug report proved that GopherTrunk's wideband DDC starved the P25 demodulator with chunks too short to hold a frame sync word — except the sync detector buffers across chunks, the incriminating log line only fires while unlocked, and the raw capture was 50% pinned to the ADC rails. The fix was turning the gain down.

  • From the Issue Tracker, Part 7: The LSM Myth — When Your Own Docs Are the Bug

    August 19, 2026

    GopherTrunk's docs, config comments, and UI labels all taught that simulcast P25 sites need the CQPSK demodulator. A user proved a genuine three-tower simulcast system decodes fine in C4FM — and that forcing CQPSK kills it. The real fault was a gain value, and the real fix was rewriting our own guidance across every surface it had leaked into.

  • From the Issue Tracker, Part 6: CQPSK in Four Acts — Fixing the Linear Path One Layer at a Time

    August 18, 2026

    A P25 control channel that decoded perfectly in C4FM produced almost nothing in CQPSK mode. The fix took four rounds — a missing carrier-recovery stage, a multipath-poisoned frequency seed, a fractionally-spaced equalizer, and a BCH hot path that only appeared once locking finally worked — and the most convincing piece of evidence in the thread was a broken instrument.

  • From the Issue Tracker, Part 5: Ten Megasamples — When the Bug Is in the Samples Themselves

    August 17, 2026

    Raising an Airspy R2 from 2.5 to 10 MS/s made every wideband tap go dark, including the strong one — two real bugs got fixed, an alarming AGC number turned out to be normal, and an independent-resampler A/B proved the remaining 10 dB deficit was recorded into the capture itself.

  • From the Issue Tracker, Part 4: The Dongle That Heard Nothing — One Line in a Register Table

    August 16, 2026

    An RTL-SDR Blog V4 that only ever received noise survived four confident wrong diagnoses, a crystal set wrong and then wrong again, and a missing input-routing block — until the reporter read the register tables and found the one value that had to be 1.

  • From the Issue Tracker, Part 3: Encrypted, Says Who — Four Layers Between a Flag and Its Metadata

    August 15, 2026

    A P25 Phase 2 system flagged every encrypted call correctly but never reported which algorithm or key — because a fictional MAC opcode, a missing carrier loop, a 48-bit sync constant in a 40-bit field, and a swapped dibit map were stacked on top of each other.

  • From the Issue Tracker, Part 2: The Talker-Alias Hunt — Three Wrong Transports and an Architectural Gate

    August 14, 2026

    A month of chasing blank P25 talker aliases through three wrong transport theories, until a per-opcode census and SDRTrunk ground truth revealed the aliases were riding traffic-channel signalling — and GopherTrunk's decoder was architecturally gated behind winning a voice tuner.

  • From the Issue Tracker, Part 1: The First P25 Lock — Eleven Fixes Between 'Trying' and 'Locked'

    August 13, 2026

    A P25 control channel that SDRTrunk and OP25 decoded in five seconds took GopherTrunk eleven fixes over five days to lock — and the last two bugs were a wrong BCH generator polynomial and a wrong CRC variant that every synthetic round-trip test had happily agreed with.

See all posts or subscribe via RSS.

Start scanning in minutes

GopherTrunk turns a cheap RTL-SDR dongle into a full digital-trunking scanner — P25, DMR, TETRA, NXDN and more, decoded by one pure-Go static binary with nothing else to install. Download the latest build and follow your first system tonight.

Download GopherTrunk v1.2.1 →

Help keep GopherTrunk growing

GopherTrunk is free, open source, and built in spare time. If it's earned a spot in your shack, a small tip funds the next protocol, feature, and guide — and keeps it all free for everyone.

Buy me a coffee GitHub Sponsors
Edit this page on GitHub →

Join the GopherTrunk community

Stuck on a system, IDing a mystery signal, or have a feature in mind? Ask on the forum or swap notes with other operators on Discord and Reddit — questions get answered fast.

Visit the Forum Join the Discord r/GopherTrunk

Project

  • README
  • License
  • Changelog
  • Security

Community

  • Discord
  • Reddit — r/GopherTrunk
  • GitHub Sponsors
  • Ko-fi
  • Issues
  • More ways to help

Built with

  • Jekyll + GitHub Pages
  • Custom layout, no theme
  • Apache 2.0 licensed
© 2026 GopherTrunk contributors. Site map · Page generated by GitHub Pages.

Have you tried GopherTrunk yet?

GopherTrunk turns a cheap RTL-SDR dongle into a full digital-trunking scanner — P25, DMR, TETRA, NXDN and more, decoded by one pure-Go static binary with nothing else to install. Grab the latest build and follow your first system tonight.

Download GopherTrunk

Enjoying GopherTrunk? Give it a star ⭐

GopherTrunk is free and open source, built in the open by a tiny team. A GitHub star costs you one click, helps other scanner operators find it, and keeps the project moving. Would you drop one?

Star View on GitHub

Disclosures

Analytics. This site uses Google Analytics to collect site-usage statistics — such as which pages are visited, how long visitors stay, and how they found the site — to measure site performance and help us improve the documentation.

Affiliate links. As an Amazon Associate we earn from qualifying purchases. Some hardware links on this site are affiliate links: if you buy through them we may earn a commission at no additional cost to you. This never changes which gear we recommend, and the software stays free and open source either way. How GopherTrunk is funded →

By continuing to use this site, you acknowledge these practices.