docker/cli · error
tty service logs only supported with --raw
Error message
tty service logs only supported with --raw
What it means
When `docker service logs` targets a TASK (not a service — the service lookup failed with NotFound at line 85, then the task was found at line 88), and that task's container spec has `TTY: true` (line 98), the CLI cannot apply its pretty-printing pipeline (task name resolution, slot padding, detail parsing via stdcopy). TTY container output is raw terminal data that is not multiplexed into stdout/stderr streams. This error fires at logs.go:105-106 when `tty && !opts.raw`, instructing the user to pass `--raw`.
Solutions
- Add the `--raw` flag: `docker service logs --raw <task-id>`
- Recreate the service without `--tty` if you need pretty-printed, multiplexed logs
- Pipe the raw output through your own formatter if custom formatting is needed
Example fix
# before docker service logs abc123def456 # error: tty service logs only supported with --raw # after docker service logs --raw abc123def456
Defensive patterns
Strategy: validation
Validate before calling
// Before fetching task logs, check TTY status
func shouldUseRawForTask(ctx context.Context, c client.APIClient, taskID string) (bool, error) {
res, err := c.TaskInspect(ctx, taskID, client.TaskInspectOptions{})
if err != nil {
return false, err
}
return res.Task.Spec.ContainerSpec.TTY, nil
}
// If TTY is true, always pass --raw (opts.raw = true) Prevention
- Always pass --raw when fetching logs for services/tasks created with --tty
- Document which services use TTY so operators know to add --raw for logs
- Avoid using --tty for services where you need structured, pretty-printed logs
When it happens
Trigger: Running `docker service logs <task-id>` where the underlying service/task was created with `--tty` (allocating a pseudo-TTY), without passing `--raw`. The code path is: ServiceInspect returns NotFound → TaskInspect succeeds → TTY check fails.
Common situations: A service was created with `--tty` (common for interactive workloads), and an operator runs `docker service logs <task>` expecting formatted output. The pretty-printer cannot parse raw TTY byte streams.
Related errors
- error: cannot perform an interactive login from a non-TTY…
- --format is incompatible with human friendly format
- cannot supply extra formatting options to the pretty…
- placement preference must be of the format
- invalid credential spec: value must be prefixed with…
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/0d1d10a006c48c4c.
Report an issue: GitHub.
Appendix: source
Thrown at cli/command/service/logs.go:106
res, err := apiClient.TaskInspect(ctx, opts.target, client.TaskInspectOptions{})
if err != nil {
if errdefs.IsNotFound(err) {
// if the task isn't found, rewrite the error to be clear
// that we looked for services AND tasks and found none
err = fmt.Errorf("no such task or service: %v", opts.target)
}
return err
}
tty = res.Task.Spec.ContainerSpec.TTY
maxLength = getMaxLength(res.Task.Slot)
// we can't prettify tty logs. tell the user that this is the case.
// this is why we assign the logs function to a variable and delay calling
// it. we want to check this before we make the call and checking twice in
// each branch is even sloppier than this CLI disaster already is
if tty && !opts.raw {
return errors.New("tty service logs only supported with --raw")
}
// now get the logs
responseBody, err = apiClient.TaskLogs(ctx, opts.target, client.TaskLogsOptions{
ShowStdout: true,
ShowStderr: true,
Since: opts.since,
Timestamps: opts.timestamps,
Follow: opts.follow,
Tail: opts.tail,
// get the details if we request it OR if we're not doing raw mode
// (we need them for the context to pretty print)
Details: opts.details || !opts.raw,
})
if err != nil {
return err
}
defer responseBody.Close()View on GitHub (pinned to 4f84911bfe)