Skip to content

exceptions

napt.exceptions

Exception hierarchy for NAPT.

This module defines a custom exception hierarchy that allows library users to distinguish between different types of errors. All exceptions inherit from NAPTError, allowing users to catch all NAPT errors with a single except clause if needed.

Example

Catching specific error types:

from napt.core import discover_recipe
from napt.exceptions import ConfigError, NetworkError

try:
    result = discover_recipe(Path("recipe.yaml"), Path("./downloads"))
except ConfigError as e:
    print(f"Configuration error: {e}")
except NetworkError as e:
    print(f"Network error: {e}")

Catching all NAPT errors:

from napt.exceptions import NAPTError

try:
    result = discover_recipe(Path("recipe.yaml"), Path("./downloads"))
except NAPTError as e:
    print(f"NAPT error: {e}")

NAPTError

Bases: Exception

Base exception for all NAPT errors.

All NAPT-specific exceptions inherit from this class, allowing users to catch all NAPT errors with a single except clause if needed.

Source code in napt/exceptions.py
class NAPTError(Exception):
    """Base exception for all NAPT errors.

    All NAPT-specific exceptions inherit from this class, allowing users
    to catch all NAPT errors with a single except clause if needed.
    """

    pass

ConfigError

Bases: NAPTError

Raised for configuration-related errors.

This exception is raised when there are problems with:

  • YAML parse errors (syntax errors, invalid structure)
  • Missing required configuration fields (e.g., no apps defined, missing 'source.strategy' field)
  • Invalid strategy configuration (unknown strategy name, invalid strategy parameters)
  • Missing recipe files (file not found)
  • Recipe validation failures (invalid recipe structure, missing required app fields)
Example

Catching configuration errors:

from napt.exceptions import ConfigError

try:
    config = load_effective_config(Path("invalid.yaml"))
except ConfigError as e:
    print(f"Config error: {e}")

Source code in napt/exceptions.py
class ConfigError(NAPTError):
    """Raised for configuration-related errors.

    This exception is raised when there are problems with:

    - YAML parse errors (syntax errors, invalid structure)
    - Missing required configuration fields (e.g., no apps defined, missing
        'source.strategy' field)
    - Invalid strategy configuration (unknown strategy name, invalid strategy
        parameters)
    - Missing recipe files (file not found)
    - Recipe validation failures (invalid recipe structure, missing required
        app fields)

    Example:
        Catching configuration errors:
            ```python
            from napt.exceptions import ConfigError

            try:
                config = load_effective_config(Path("invalid.yaml"))
            except ConfigError as e:
                print(f"Config error: {e}")
            ```
    """

    pass

NetworkError

Bases: NAPTError

Raised for network/download-related errors.

This exception is raised when there are problems with:

  • Download failures (HTTP errors, connection timeouts, network unreachable)
  • API call failures (GitHub API errors, JSON API endpoint failures, authentication issues)
  • Network-related version extraction errors (API response parsing failures)
Example

Catching network errors:

from napt.exceptions import NetworkError

try:
    result = discover_recipe(Path("recipe.yaml"), Path("./downloads"))
except NetworkError as e:
    print(f"Network error: {e}")

Source code in napt/exceptions.py
class NetworkError(NAPTError):
    """Raised for network/download-related errors.

    This exception is raised when there are problems with:

    - Download failures (HTTP errors, connection timeouts, network
        unreachable)
    - API call failures (GitHub API errors, JSON API endpoint failures,
        authentication issues)
    - Network-related version extraction errors (API response parsing
        failures)

    Example:
        Catching network errors:
            ```python
            from napt.exceptions import NetworkError

            try:
                result = discover_recipe(Path("recipe.yaml"), Path("./downloads"))
            except NetworkError as e:
                print(f"Network error: {e}")
            ```
    """

    pass

PackagingError

Bases: NAPTError

Raised for packaging/build-related errors.

This exception is raised when there are problems with:

  • Build failures (PSADT template processing errors, file operations, directory creation failures)
  • Missing build tools (IntuneWinAppUtil.exe not found, PSADT template missing)
  • MSI extraction errors (failed to read MSI ProductVersion, unsupported MSI format)
  • Packaging operations (IntuneWinAppUtil.exe execution failures, invalid build directory structure)
  • Malformed .intunewin files (invalid ZIP structure, missing Detection.xml, missing required encryption fields)
Example

Catching packaging errors:

from napt.exceptions import PackagingError

try:
    build_package(Path("recipe.yaml"), Path("./builds"))
except PackagingError as e:
    print(f"Packaging error: {e}")

Source code in napt/exceptions.py
class PackagingError(NAPTError):
    """Raised for packaging/build-related errors.

    This exception is raised when there are problems with:

    - Build failures (PSADT template processing errors, file operations,
        directory creation failures)
    - Missing build tools (IntuneWinAppUtil.exe not found, PSADT template
        missing)
    - MSI extraction errors (failed to read MSI ProductVersion, unsupported
        MSI format)
    - Packaging operations (IntuneWinAppUtil.exe execution failures, invalid
        build directory structure)
    - Malformed .intunewin files (invalid ZIP structure, missing Detection.xml,
        missing required encryption fields)

    Example:
        Catching packaging errors:
            ```python
            from napt.exceptions import PackagingError

            try:
                build_package(Path("recipe.yaml"), Path("./builds"))
            except PackagingError as e:
                print(f"Packaging error: {e}")
            ```
    """

    pass

AuthError

Bases: NAPTError

Raised for authentication and authorization errors.

This exception is raised when there are problems with:

  • azure-identity credential chain exhausted (all credential types unavailable or failed)
  • Graph API 401 Unauthorized or 403 Forbidden responses
  • Device code flow timeout or user cancellation
  • Invalid or missing credentials for the DeviceCodeCredential fallback
Example

Catching auth errors:

from napt.exceptions import AuthError

try:
    result = upload_package(Path("recipe.yaml"))
except AuthError as e:
    print(f"Auth error: {e}")

Source code in napt/exceptions.py
class AuthError(NAPTError):
    """Raised for authentication and authorization errors.

    This exception is raised when there are problems with:

    - azure-identity credential chain exhausted (all credential types
        unavailable or failed)
    - Graph API 401 Unauthorized or 403 Forbidden responses
    - Device code flow timeout or user cancellation
    - Invalid or missing credentials for the DeviceCodeCredential fallback

    Example:
        Catching auth errors:
            ```python
            from napt.exceptions import AuthError

            try:
                result = upload_package(Path("recipe.yaml"))
            except AuthError as e:
                print(f"Auth error: {e}")
            ```
    """

    pass

NotModifiedError

Bases: Exception

Raised when a conditional HTTP request returns 304 Not Modified.

This exception is raised when download_file() receives HTTP 304, meaning the server has confirmed that the remote content has not changed since the last request. The function is expected to return a file on disk, and with a 304 response there is no file to return, so it raises instead.

Inherits from Exception (not NAPTError) so that broad catches of all NAPT errors do not suppress 304 responses. Callers that supply an ETag must handle this explicitly.

Example

Handling a conditional download:

from napt.exceptions import NotModifiedError

try:
    result = download_file(url, dest, etag=cached_etag)
except NotModifiedError:
    # Server confirmed content unchanged, use the cached file
    pass

Source code in napt/exceptions.py
class NotModifiedError(Exception):
    """Raised when a conditional HTTP request returns 304 Not Modified.

    This exception is raised when download_file() receives HTTP 304, meaning
    the server has confirmed that the remote content has not changed since the
    last request. The function is expected to return a file on disk, and with
    a 304 response there is no file to return, so it raises instead.

    Inherits from Exception (not NAPTError) so that broad catches of all NAPT
    errors do not suppress 304 responses. Callers that supply an ETag must
    handle this explicitly.

    Example:
        Handling a conditional download:
            ```python
            from napt.exceptions import NotModifiedError

            try:
                result = download_file(url, dest, etag=cached_etag)
            except NotModifiedError:
                # Server confirmed content unchanged, use the cached file
                pass
            ```
    """

    pass