pion/webrtc · error
output not opened
Error message
output not opened
What it means
errOutputNotOpened is returned by oggwriter.NewWriter when the provided io.Writer is nil, and by the internal stream-access path when w.stream is nil (e.g. writing before a valid output was attached). It indicates the writer has no destination to serialize Ogg pages into.
Source
Thrown at pkg/media/oggwriter/oggwriter.go:49
maxOpusPacketSamples = opusGranuleSampleRate * 120 / 1000
defaultChannelCount = 2
channelMappingFamily0 = 0
channelMappingFamily1 = 1
channelMappingFamily2 = 2
channelMappingFamily255 = 255
idPageSignature = "OpusHead"
commentPageSignature = "OpusTags"
defaultVendor = "pion"
pageHeaderSignature = "OggS"
pageHeaderSize = 27
maxOggPageSegments = 255
noGranulePosition = ^uint64(0)
maxUint32Length = uint64(1<<32 - 1)
)
var (
errFileNotOpened = errors.New("file not opened")
errOutputNotOpened = errors.New("output not opened")
errInvalidNilPacket = errors.New("invalid nil packet")
errDuplicateTrackSSRC = errors.New("duplicate Ogg track SSRC")
errDuplicateTrackSerial = errors.New("duplicate Ogg track serial")
errTracksStarted = errors.New("cannot add Ogg tracks after writing has started")
errPacketSSRCMismatch = errors.New("RTP packet SSRC does not match Ogg track SSRC")
errInvalidOpusPacket = errors.New("invalid Opus packet")
errInvalidChannelCount = errors.New("invalid channel count")
errInvalidChannelMap = errors.New("invalid channel mapping")
errInvalidOpusTags = errors.New("invalid OpusTags")
)
type pageRewriter interface {
io.Seeker
io.WriterAt
}
type writerConfig struct {
sampleRate uint32View on GitHub (pinned to 8c25dc09fa)
Solutions
- Create/open the destination and check its error before NewWriter
- Never construct Writer directly without a stream; use NewWriter
- Verify the file is not closed/nil before each WriteRTP/Close sequence
Example fix
// before
f, _ := os.Create("out.ogg")
w, err := oggwriter.NewWriter(f) // errOutputNotOpened if f nil
// after
f, err := os.Create("out.ogg")
if err != nil {
return err
}
w, err := oggwriter.NewWriter(f) Defensive patterns
Strategy: validation
Validate before calling
if out == nil {
return errors.New("ogg writer requires a non-nil io.Writer")
}
w, err := oggwriter.NewWriter(out) Type guard
func hasOutputStream(w *oggwriter.Writer) bool {
return w != nil
} Try / catch
w, err := oggwriter.NewWriter(out)
if errors.Is(err, oggwriter.ErrOutputNotOpened) {
return fmt.Errorf("ogg output missing: %w", err)
} Prevention
- Construct writers only via NewWriter with a checked, open destination
- Do not close the underlying file before writer.Close()
- Avoid zero-value Writer structs; always use the constructor
When it happens
Trigger: NewWriter(nil) (oggwriter.go:391); internal write path encountering w.stream == nil (oggwriter.go:432); asserted by TestOggWriter_NewWriterRequiresOutput.
Common situations: Ignoring the error from os.Create so a nil file reaches NewWriter, constructing a Writer via a struct literal without setting stream, closing the file and continuing to write.
Related errors
AI-assisted analysis of pion/webrtc@8c25dc09fa (2026-09-03).
Data as JSON: /api/errors/74805ae72a8ad1dd.
Report an issue: GitHub.