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 strictreturns
parameters- Package installations via
npm
,pip
, or other tools - Service restarts that return warnings
- Check
puppet agent --test --debug
output - Review system logs around the Puppet run time
- Test commands manually with the same environment variables
- Validate file permissions and paths