microsoft / microsoft/vscode-documentdb

Discussion: upstream our Docker failure-diagnosis enhancements to @microsoft/vscode-container-client

Open
#840 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement feedback wanted P3
Dominant language
TypeScript
Stars
31
Forks
22
Avg merge
2d 20h
Merged PRs (30d)
21

Description

Context

While building the Local Quick Start Docker readiness pipeline (plan: docs/ai-and-plans/local-quickstart/docker-readiness-implementation-plan.md) we found that @microsoft/vscode-container-client is very good at invoking Docker and cancelling it, but it discards exactly the evidence a consumer needs to diagnose a failure.

We worked around this inside our own code. Several of those workarounds look generic enough that other consumers of the package would benefit, so this issue is to decide whether we open a PR or an issue upstream, and what exactly to propose.

Versions this was verified against: @microsoft/vscode-container-client@^0.5.4, @microsoft/vscode-processutils@^0.2.2.

What we found, verified by reading the installed package

  1. A non zero exit loses the Docker error text.
    spawnStreamAsync (@microsoft/vscode-processutils/dist/esm/utils/spawnStreamAsync.js) rejects with ChildProcessError('Process exited with code <n>'). Docker's own stderr went to the caller supplied stdErrPipe and is not attached to the error. A consumer that classifies failures from the rejected error's message therefore sees nothing useful. In our case, an Ubuntu user without docker group membership produced the string Process exited with code 1, and nothing else.

  2. Output is discarded on failure.
    In ShellStreamCommandRunnerFactory (dist/esm/commandRunners/shellStream.js), the stdout accumulator is destroyed in finally and parse never runs when the command rejects. This matters because docker info --format {{json .}} prints a valid JSON body containing ServerErrors and still exits non zero when the daemon is unreachable. The single most stable failure signal Docker offers is thrown away before any consumer can read it.

  3. The info schema strips useful fields.
    DockerInfoRecordSchema (dist/esm/clients/DockerClientBase/DockerInfoRecord.d.ts) keeps only OperatingSystem and OSType. Architecture, ServerVersion, and ServerErrors are stripped. InfoItem.raw does preserve the body, so the workaround is to parse the same JSON a second time with a local schema.

  4. Timeout and user cancellation are indistinguishable.
    Both surface as CancellationError, so a consumer that implements a deadline must separately track which cancellation source fired in order to tell "Docker did not respond" from "the user closed the panel".

What we implemented locally as a result

All in src/services/localQuickStart/:

  • dockerProbes.ts: a CapturingTeeWritable that tees stdout and stderr into local buffers while still forwarding to the masked OutputChannel, so a rejected command still yields its output. Each probe returns a DockerProbeEvidence record with exit code, spawn errno, stdout, stderr, how it ended (exit, deadline, cancellation), and duration.
  • A local zod schema over InfoItem.raw for OSType, Architecture, ServerVersion, and ServerErrors.
  • Daemon architecture normalization, since docker info reports x86_64 and aarch64 rather than amd64 and arm64.
  • dockerReadinessClassification.ts: evidence to typed failure classification, with errno ranked above error text.
  • Endpoint resolution (DOCKER_HOST, then DOCKER_CONTEXT, then the current context from docker context ls, then the platform default) plus an fs.access and net.connect reachability probe for errno level evidence.

Candidate upstream proposals

# Proposal Generality Breaking risk
1 Attach captured stderr (and stdout) to ChildProcessError High None
2 Run parse on a non zero exit when output is present, or expose the accumulated output on the thrown error High Possible for consumers relying on parse never running on failure
3 Widen DockerInfoRecordSchema to include Architecture, ServerVersion, and ServerErrors High None
4 Let the runner distinguish a deadline from a caller cancellation Medium None
5 Contribute the endpoint resolution helper Medium None
6 Contribute the errno based endpoint reachability probe Lower, more opinionated None

Items 1 to 3 are the highest value and the least controversial. Item 1 alone would remove most of our shim.

Open questions to resolve before acting

  • Confirm where the package is developed and whether it accepts external contributions. It is understood to come out of the Microsoft Container Tools and Docker extension work, but the contribution process needs checking.
  • Is item 2 a breaking behavior change for existing consumers?
  • Do we want to own the PR, or file an issue upstream with these findings and let the owners choose the shape?
  • If something lands upstream, which of our local workarounds get deleted, and does that require a minimum package version bump in package.json?

Why bother

Our workaround is small, but it is a shim over a library we do not own, sitting on the critical path of a first run experience. Every future consumer of this package that tries to diagnose a Docker failure will rediscover the same three findings. Landing items 1 to 3 upstream removes our shim and improves the package for everyone.

References

  • src/services/localQuickStart/dockerProbes.ts
  • src/services/localQuickStart/dockerReadinessClassification.ts
  • src/services/localQuickStart/DockerReadinessService.ts
  • Plan section "Verified Execution-Path Constraints" in docs/ai-and-plans/local-quickstart/docker-readiness-implementation-plan.md, which records the same findings with their consequences

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/services/localQuickStart/dockerProbes.ts and dockerReadinessClassification.ts, then read the verified execution-path constraints in docs/ai-and-plans/local-quickstart/docker-readiness-implementation-plan.md. Confirm the upstream contribution process and assess proposals 1–3, including the effect on package.json and local workarounds. Done means an agreed upstream proposal or issue scope, not an implementation in this repository.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, typescript
Domain
developer-experience, devops, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.