dagger/dagger · error

service digest is empty

Error message

service digest is empty

What it means

Service.Hostname computes a deterministic DNS hostname from a content digest for container=>container or container=>host services, but was handed an empty digest. Without a digest there is nothing to hash into a host name, so it fails with this error. Callers (Endpoint, startContainer, startReverseTunnel) normally derive the digest from the service registration, so an empty dig means the service was looked up before registration.

Source

Thrown at core/service.go:342

		return "", err
	}

	switch {
	case svc.TunnelUpstream.Self() != nil: // host=>container (127.0.0.1)
		svcs, err := query.Services(ctx)
		if err != nil {
			return "", err
		}
		upstream, err := svcs.Get(ctx, dig, true)
		if err != nil {
			return "", err
		}

		return upstream.Host, nil
	case svc.Container.Self() != nil, // container=>container
		len(svc.HostSockets) > 0: // container=>host
		if dig == "" {
			return "", errors.New("service digest is empty")
		}
		return network.HostHash(dig), nil
	default:
		return "", errors.New("unknown service type")
	}
}

func (svc *Service) Ports(ctx context.Context, dig digest.Digest) ([]Port, error) {
	query, err := CurrentQuery(ctx)
	if err != nil {
		return nil, err
	}

	switch {
	case svc.TunnelUpstream.Self() != nil, len(svc.HostSockets) > 0:
		svcs, err := query.Services(ctx)
		if err != nil {
			return nil, err

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Evaluate/start the service (or call it via Container.WithServiceBinding and use the dependent container's Endpoint) so a digest is registered before requesting the hostname.
  2. Use the documented API surface (Container.Endpoint / Service endpoints via SDK) instead of calling Hostname with a manually supplied digest.
  3. If using a custom hostname, set it with WithHostname so the digest path is bypassed.

Example fix

// before
host, _ := svc.Hostname(ctx, "") // empty digest
// after
host, err := containerWithSvc.Endpoint(ctx) // let the engine resolve the registered digest
Defensive patterns

Strategy: validation

Validate before calling

dig := serviceDigest(svc) // from service registration
if dig == "" {
    // evaluate/start the service first, or use the dependent container's Endpoint API
    return errors.New("service not registered; cannot compute hostname")
}

Try / catch

if err != nil && strings.Contains(err.Error(), "service digest is empty") {
    // evaluate the service (e.g. run a dependent container) then retry the endpoint lookup
}

Prevention

When it happens

Trigger: Calling Hostname (directly or via Service.Endpoint / when starting a container or reverse tunnel) with dig == "" while the service is a container service or has HostSockets — e.g. querying Endpoint on a service that was never evaluated/registered in the services registry for the current query.

Common situations: Calling Endpoint/hostname on a Service obtained but not yet started or evaluated; custom module code invoking endpoint APIs before binding the service to a container; services referenced across queries without re-registration.

Related errors


AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05). Data as JSON: /api/errors/77152a49409c30fc. Report an issue: GitHub.