How to Fix “Puppet Error: returned 1 instead of one of [0]” and Retrieve Actual Error Messages


2 views

When working with Puppet manifests, you might encounter the frustrating error message:

Error: /Stage[main]/Main/Exec[some_command]: Failed to call refresh: Command 'some_command' returned 1 instead of one of [0]

This occurs when an exec resource returns a non-zero exit status (typically 1), while Puppet expects only exit code 0 (success).

Puppet treats exit codes strictly because:

  • 0 means success (Puppet will consider the resource applied)
  • Non-zero means failure (Puppet will report an error)

Common scenarios where this occurs:

exec { 'install_package':
  command => '/usr/bin/apt-get install nonexistent-package',
  path    => ['/usr/bin', '/bin'],
}

To see what's really failing, use these techniques:

Method 1: Enable Detailed Logging

exec { 'run_script':
  command     => '/path/to/script.sh',
  logoutput   => true,  # Logs stdout/stderr to Puppet's log
  returns     => [0, 1] # Accept multiple exit codes
}

Method 2: Redirect Output to Files

exec { 'debug_command':
  command => '/path/to/command > /tmp/command.stdout 2> /tmp/command.stderr',
  path    => ['/bin', '/usr/bin']
}

Method 3: Use Puppet Debug Mode

puppet apply --debug manifest.pp

Solution 1: Handle Expected Non-Zero Codes

exec { 'grep_something':
  command => 'grep pattern /some/file',
  returns => [0, 1], # grep returns 1 when pattern not found
}

Solution 2: Better Error Handling with Unless/Onlyif

exec { 'safe_command':
  command => '/usr/bin/dangerous-operation',
  unless  => '/usr/bin/test -f /var/lock/safe-to-run',
}

Solution 3: Write Wrapper Scripts

#!/bin/bash
# wrapper.sh
/path/to/original/command "$@"
exit 0 # Always return success after logging

Then in Puppet:

file { '/usr/local/bin/safe_wrapper':
  content => file('mymodule/wrapper.sh'),
  mode    => '0755',
}

exec { 'use_wrapper':
  command => '/usr/local/bin/safe_wrapper args',
}

For complex cases, consider:

  • Checking system resource limits
  • Verifying file permissions
  • Running commands manually as the Puppet user
  • Using strace to identify system call failures

When Puppet returns the error "returned 1 instead of one of [0]", it typically means an executed command or script exited with status 1 (failure) when Puppet expected exit code 0 (success). This generic message hides the actual underlying error, making debugging frustrating.

Puppet strictly follows Unix exit code conventions:


0 = Success
1-255 = Failure (with application-specific meanings)

Many commands use 1 for general errors, while 2 often indicates misuse (like invalid arguments).

Use these methods to surface hidden errors:

Method 1: Log Output to Puppet Server


exec { 'my_command':
  command     => '/usr/bin/failing_command 2>&1 | logger -t puppet-errors',
  returns     => [0, 1], # Allow both success and failure
  logoutput   => true,
}

Then check syslog: grep puppet-errors /var/log/syslog

Method 2: Store Output in a File


exec { 'debug_command':
  command => '/usr/bin/failing_command 2>&1 > /tmp/puppet_debug.log',
  returns => [0, 1],
}

Method 3: Use Puppet's catch_error Pattern


$output = catch_error() || {
  exec { '/usr/bin/failing_command':
    returns => [0, 1]
  }
}
notice("Command output: ${output}")

For complex scenarios, create a wrapper script:


#!/bin/bash
/usr/bin/failing_command
exit_status=$?

if [ $exit_status -eq 1 ]; then
  echo "Custom error handling for exit 1" >&2
  exit 0 # Tell Puppet this is acceptable
fi

exit $exit_status

These resource types frequently cause exit code issues:

  • exec resources with strict returns parameters
  • Package installations via npm, pip, or other tools
  • Service restarts that return warnings
  1. Check puppet agent --test --debug output
  2. Review system logs around the Puppet run time
  3. Test commands manually with the same environment variables
  4. Validate file permissions and paths