docmirror/dev-sidecar · warning

server process SIGPIPE, code: ${code}, signal:

Error message

server process SIGPIPE, code: ${code}, signal:

What it means

A warning log from the `SIGPIPE` handler on the forked mitmproxy child (packages/core/src/modules/server/index.js:118-120). It fires when the child process receives a SIGPIPE signal, typically caused by writing to a closed pipe — most commonly the parent (core) process died or closed the IPC stdio pipes while the child was still logging or sending messages.

Source

Thrown at packages/core/src/modules/server/index.js:119

      log.info('保存 running.json 运行时配置文件成功:', runningConfigPath)
    } catch (e) {
      log.error('保存 running.json 运行时配置文件失败:', runningConfigPath, ', error:', e)
      throw e
    }
    const serverProcess = fork(mitmproxyPath, [runningConfigPath])
    server = {
      id: serverProcess.pid,
      process: serverProcess,
      port: serverConfig.port,
      close () {
        serverProcess.send({ type: 'action', event: { key: 'close' } })
      },
    }
    serverProcess.on('beforeExit', (code) => {
      log.warn('server process beforeExit, code:', code)
    })
    serverProcess.on('SIGPIPE', (code, signal) => {
      log.warn(`server process SIGPIPE, code: ${code}, signal:`, signal)
    })
    serverProcess.on('exit', (code, signal) => {
      log.warn(`server process exit, code: ${code}, signal:`, signal)
    })
    serverProcess.on('uncaughtException', (err, origin) => {
      log.error('server process uncaughtException:', err)
    })
    serverProcess.on('message', (msg) => {
      log.debug('收到子进程消息:', JSON.stringify(msg))
      if (msg.type === 'status') {
        fireStatus(msg.event)
      } else if (msg.type === 'error') {
        let code = ''
        if (msg.event.code) {
          code = msg.event.code
        }
        fireStatus(false) // 启动失败
        event.fire('error', { key: 'server', value: code, error: msg.event, message: msg.message })

View on GitHub (pinned to 7710cd56cc)

Solutions

  1. Usually a symptom, not the cause: find why the pipe broke — check whether the parent process exited and if so why (core.log/gui.log).
  2. Ensure the child is shut down with server.close()/kill() before the parent exits so pipes close cleanly.
  3. If running headless/daemonized, redirect child stdio to files instead of a terminal pipe (`fork(mitmproxyPath, [cfg], { stdio: ['pipe','pipe','pipe','ipc'] })` plus file logging).
  4. Ignore 'ignore' stdio for the child if IPC is the only needed channel to avoid stdout EPIPE/SIGPIPE issues.

Example fix

// before
const serverProcess = fork(mitmproxyPath, [runningConfigPath])
// after
const serverProcess = fork(mitmproxyPath, [runningConfigPath], {
  stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
})
serverProcess.stdout.on('error', (e) => log.warn('child stdout pipe error:', e))
Defensive patterns

Strategy: retry

Validate before calling

// before starting, ensure config is complete so the child does not drain-exit
const cfg = DevSidecar.api.config.get()
if (!cfg.server || !cfg.server.port || !cfg.server.mitmproxyPath) {
  throw new Error('server config incomplete; fix ~/.dev-sidecar/config.json before startup')
}

Try / catch

let restarting = false
serverProcess.on('beforeExit', (code) => {
  log.warn('server process beforeExit, code:', code)
  if (!restarting) {
    restarting = true
    serverApi.restart({ mitmproxyPath }).finally(() => { restarting = false })
  }
})

Prevention

When it happens

Trigger: Parent core process exits/crashes while the child keeps writing to stdout or IPC channel; the IPC pipe between parent and child is closed while the child sends status/speed messages.

Common situations: Killing the GUI/CLI parent process (task manager, crash) leaving the orphaned mitmproxy child; terminal window closed so stdout pipe breaks; EPIPE storms when piping logs to a short-lived consumer.

Related errors


AI-assisted analysis of docmirror/dev-sidecar@7710cd56cc (2026-08-31). Data as JSON: /api/errors/730d317a77e59397. Report an issue: GitHub.