{"record":{"id":"af09c62fe0088895","repo":"jordansissel/fpm","slug":"editor-failed-exit-code-exitstatus-fu","errorCode":null,"errorMessage":"'#{editor}' failed (exit code #{$?.exitstatus}) Full command was: #{command}","messagePattern":"'#(.+?)' failed \\(exit code #(.+?)\\) Full command was: #(.+?)","errorType":"exception","errorClass":"FPM::Util::ProcessFailed","httpStatus":null,"severity":"error","filePath":"lib/fpm/package.rb","lineNumber":372,"sourceCode":"  def to_s(fmt=nil)\n    fmt = \"NAME.EXTENSION\" if fmt.nil?\n    return fmt.gsub(\"ARCH\", to_s_arch) \\\n      .gsub(\"NAME\",         to_s_name) \\\n      .gsub(\"FULLVERSION\",  to_s_fullversion) \\\n      .gsub(\"VERSION\",      to_s_version) \\\n      .gsub(\"ITERATION\",    to_s_iteration) \\\n      .gsub(\"EPOCH\",        to_s_epoch) \\\n      .gsub(\"TYPE\",         to_s_type) \\\n      .gsub(\"EXTENSION\",    to_s_extension)\n  end # def to_s\n\n  def edit_file(path)\n    editor = ENV['FPM_EDITOR'] || ENV['EDITOR'] || 'vi'\n    logger.info(\"Launching editor\", :file => path)\n    command = \"#{editor} #{Shellwords.escape(path)}\"\n    system(\"#{editor} #{Shellwords.escape(path)}\")\n    if !$?.success?\n      raise ProcessFailed.new(\"'#{editor}' failed (exit code \" \\\n                              \"#{$?.exitstatus}) Full command was: \" \\\n                              \"#{command}\");\n    end\n\n    if File.size(path) == 0\n      raise \"Empty file after editing: #{path.inspect}\"\n    end\n  end # def edit_file\n\n  # This method removes excluded files from the staging_path. Subclasses can\n  # remove the files during the input phase rather than deleting them here\n  def exclude\n    return if attributes[:excludes].nil?\n\n    if @attributes.include?(:prefix)\n      installdir = staging_path(@attributes[:prefix])\n    else\n      installdir = staging_path","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/jordansissel/fpm/blob/b6d77ba72a560b687723376a0e5115c3a92634ad/lib/fpm/package.rb#L354-L390","documentation":"With --edit, fpm writes the generated spec/metadata to a temp file and launches an editor via system(): the program from $FPM_EDITOR, else $EDITOR, else 'vi'. If that editor process exits non-zero, FPM::Util::ProcessFailed is raised with the exit status and the full command line. The failure belongs to the editor process, not to fpm's packaging logic.","triggerScenarios":"Running 'fpm --edit ...' where FPM_EDITOR/EDITOR points to a missing or crashing binary; a headless/CI shell with no TTY so vi exits with an error; the editor being killed or quitting with a non-zero status.","commonSituations":"CI pipelines that inherited --edit from a local alias; EDITOR set to a GUI editor needing a display; wrapper-script editors whose last command returns non-zero; minimal containers where even the default vi is absent.","solutions":["Export a working editor before running: FPM_EDITOR=vim (and confirm 'which vim' succeeds)","Drop --edit in non-interactive contexts and supply fields via flags (--description, --after-install, --template-scripts, ...)","If the editor is a wrapper, ensure it exits 0 on success; test with '$FPM_EDITOR /tmp/probe'","For scripted edits, point FPM_EDITOR at a non-interactive filter (e.g. a sed-based wrapper)"],"exampleFix":"# before (CI job, no TTY)\nfpm --edit -s dir -t deb ./app   # vi fails without a terminal => ProcessFailed\n\n# after: no interactive edit; set fields explicitly\nFPM_EDITOR=vim fpm --edit -s dir -t deb ./app   # local, interactive use only\nfpm -s dir -t deb --description 'My app' ./app  # CI-safe","handlingStrategy":"validation","validationCode":"editor = (ENV['FPM_EDITOR'] || ENV['EDITOR'] || 'vi').split(' ').first\nunless system('which', editor, out: File::NULL, err: File::NULL)\n  abort \"editor '#{editor}' not found; set FPM_EDITOR or drop --edit\"\nend","typeGuard":null,"tryCatchPattern":"begin\n  # invoking fpm with --edit programmatically\nrescue FPM::Util::ProcessFailed => e\n  abort \"editor failed: #{e.message}\"  # includes exit code and full command\nend","preventionTips":["Never use --edit in CI/automation; supply metadata through flags or --template-scripts instead","Export FPM_EDITOR explicitly in scripts rather than relying on ambient EDITOR state","Ensure wrapper editors exit 0 on success; test them with '$FPM_EDITOR /tmp/probe' before wiring into fpm"],"tags":["fpm","editor","subprocess","env-var","interactive","ci"],"backgroundTag":"subprocess-nonzero-exit","analyzedSha":"b6d77ba72a560b687723376a0e5115c3a92634ad","analyzedAt":"2026-08-21T16:39:02.570Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}