Skip to main content

Debugging

If you come across bugs, here are some simple debugging suggestions.

Rerun commands with --debug

The Dagger CLI tries to keep its output concise by default. If you're running into issues and want to debug with more detailed output, you can run any dagger subcommand with the --debug flag to have it reveal all available information.

Access the Dagger Engine logs

The Dagger Engine runs in a dedicated Docker container and emits log messages as it works. Here's how to access these logs:

DAGGER_ENGINE_DOCKER_CONTAINER="$(docker container list --all --filter 'name=^dagger-engine-*' --format '{{.Names}}')"
docker logs $DAGGER_ENGINE_DOCKER_CONTAINER

Enable SDK debug logs

important

The information in this section is only applicable to the Python SDK. Debug logs are not currently available for the Go and TypeScript SDKs.

The Python SDK prints debugging information at various steps of the execution flow of a module, which can be very useful in understanding what's being received from and sent to the API.

This is done using standard Python logging, so it's highly configurable (for example, saving to a file or sending to an external system like Sentry). But for a simple lowering of the default logging level to logging.DEBUG, there's a convenience function for that:

import logging

from dagger import function, object_type
from dagger.log import configure_logging

configure_logging(logging.DEBUG)


@object_type
class MyModule:
@function
def echo(self, msg: str) -> str:
return msg
note

With the TUI, you need to use a progress output that doesn't collapse on success like --progress=plain or --debug, otherwise it won't show in the terminal.

Using the command dagger call --debug echo --msg="hello", you should see a large number of debug messages, eventually ending with output similar to the below:

  ✔ connect 0.1s
✔ Debug.echo(msg: "hello"): String! 0.9s
┃ [DEBUG] dagger.mod._resolver: func => <Signature (msg: str) -> str>
┃ [DEBUG] dagger.mod._resolver: input args => {'msg': 'hello'}
┃ [DEBUG] dagger.mod._resolver: structured args => {'msg': 'hello'}
┃ [DEBUG] dagger.mod._module: result => 'hello'
┃ [DEBUG] dagger.mod._module: output => '"hello"'
┃ [DEBUG] dagger.client._session: Closing client session to GraphQL server

hello

The above gives a lot of useful information:

  • The function and parent object that the API wants to execute
  • The parent object's state
  • The function's signature
  • The user inputs before and after deserialization
  • The user inputs after being converted to more complex types (structuring)
  • The function's result before and after serialization