m1k1o/neko · error

unable to get first image

Error message

unable to get first image

What it means

createPipeline waits on the first sample from the newly created GStreamer pipeline's Sample() channel. If the channel is closed without delivering an image (ok == false), it returns 'unable to get first image'. This means the pipeline was torn down or ended before producing any frame.

Source

Thrown at server/internal/capture/screencast.go:203

	manager.logger.Info().
		Str("str", manager.pipelineStr).
		Msgf("creating pipeline")

	manager.pipeline, err = gst.CreatePipeline(manager.pipelineStr)
	if err != nil {
		return err
	}

	manager.pipeline.AttachAppsink("appsink")
	manager.pipeline.Play()
	manager.pipelinesCounter.Inc()
	manager.pipelinesActive.Set(1)

	// get first image
	select {
	case image, ok := <-manager.pipeline.Sample():
		if !ok {
			return errors.New("unable to get first image")
		} else {
			manager.setImage(image)
		}
	case <-time.After(1 * time.Second):
		return errors.New("timeouted while waiting for first image")
	}

	pipeline := manager.pipeline
	manager.wg.Go(func() {
		manager.logger.Debug().Msg("started receiving images")

		for {
			image, ok := <-pipeline.Sample()
			if !ok {
				manager.logger.Debug().Msg("stopped receiving images")
				return
			}

View on GitHub (pinned to b0f01cedea)

Solutions

  1. Retry start/Image after a short delay — transient races usually succeed on the second attempt
  2. Check that nothing stops or destroys the pipeline concurrently during startup
  3. Verify the GStreamer pipeline string is valid so the source actually produces samples
  4. Inspect logs for pipeline teardown messages around the failure time

Example fix

// before
if err := manager.start(); err != nil { return err } // unable to get first image
// after
var err error
for i := 0; i < 3; i++ {
    if err = manager.start(); err == nil || !strings.Contains(err.Error(), "first image") { break }
    time.Sleep(200 * time.Millisecond)
}
Defensive patterns

Strategy: retry

Try / catch

if err := manager.start(); err != nil {
    if err.Error() == "unable to get first image" {
        // transient: pipeline closed before first sample
        time.Sleep(300 * time.Millisecond)
        return manager.start() // retry once
    }
    return err
}

Prevention

When it happens

Trigger: The pipeline's sample channel closes during the 1-second wait — typically because the pipeline was stopped/destroyed immediately after creation, or the source ended with no samples emitted.

Common situations: Fast disconnect of the client that triggered pipeline creation races the first-sample wait; faulty GStreamer element chain exits instantly; stopping the stream from another goroutine within the first second.

Related errors


AI-assisted analysis of m1k1o/neko@b0f01cedea (2026-09-01). Data as JSON: /api/errors/304952c958362c31. Report an issue: GitHub.