Skip to content

DevpodProvider: _handle_provider_setup crashes with JSON decode error due to PTY control characters in provider list output #233

@sadpenguinn

Description

@sadpenguinn

DevpodProvider._handle_provider_setup always crashes with a JSON decode error when launching a devcontainer workspace. The error is:

Expected value but found invalid token at character 1

The root cause is that Executor:run_executor_job starts all jobs with pty = true. When a PTY is allocated, devpod detects a terminal and emits control characters (spinner frames, cursor movement sequences) before the actual JSON output. These bytes corrupt the string passed to vim.json.decode.

To reproduce

  1. Have devpod installed (v0.6.15 confirmed, likely affects all versions)
  2. Open a project that has a .devcontainer/ directory
  3. Run :RemoteStart → select Dev Containers: Launch current project in devcontainer
  4. Observe the error in the notification/progress window

You can independently verify the PTY corruption:

With PTY — devpod emits control bytes before JSON

script -q /dev/null devpod provider list --output json | cat -v

output: ^D^H^H{}

Without PTY — clean output

devpod provider list --output json

output: {}

The corrupted string hits vim.json.decode here:

-- lua/remote-nvim/providers/devpod/devpod_provider.lua:164
local provider_list_output = vim.json.decode(vim.tbl_isempty(stdout) and "{}" or
table.concat(stdout, "\n"))

Expected behavior

The devcontainer workspace launches without error. devpod provider list --output json output is
decoded as valid JSON.

Screenshot/Screencast(s)

N/A

System information

  • Local OS: macOS Darwin 25.3.0 (Apple Silicon)
  • Local Neovim version: NVIM v0.11.6
  • Remote host OS: N/A (devcontainer, local Docker)
  • Remote Neovim version: N/A

Additional context

The fix should be applied in Executor:run_executor_job — pty = true is appropriate for interactive commands like devpod up (real-time progress), but is incorrect for commands whose stdout is consumed as structured data. provider list --output json should run without PTY.

Minimal targeted workaround for _handle_provider_setup while the proper fix is implemented:

local stdout = self.local_provider.executor:job_stdout()
local raw = table.concat(stdout, "\n")
-- Extract JSON object boundaries, ignore PTY garbage around it
local json_start = raw:find("{")
local json_end = select(2, raw:find(".*}"))
local json_str = (json_start and json_end) and raw:sub(json_start, json_end) or "{}"
local provider_list_output = vim.json.decode(json_str)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions