en-US/about_PSUKG_ErrorHandling.help.txt

TOPIC
    about_PSUKG_ErrorHandling

SHORT DESCRIPTION
    Explains error handling, troubleshooting, and debugging in the PSUKG module.

LONG DESCRIPTION
    The PSUKG module provides comprehensive error handling for API interactions.
    This topic covers error types, handling strategies, and troubleshooting
    techniques.

  Error Types
    The module handles several categories of errors:

    Authentication Errors:
        - Invalid credentials (401 Unauthorized)
        - Expired tokens (automatically handled via refresh)
        - Missing authentication (connection required)

    Validation Errors:
        - Invalid parameter values (400 Bad Request)
        - Missing required fields
        - Malformed data

    Not Found Errors:
        - Resource doesn't exist (404 Not Found)
        - Invalid resource ID

    Permission Errors:
        - Insufficient permissions (403 Forbidden)
        - Operation not allowed for resource

    Rate Limiting Errors:
        - Too many requests (429 Too Many Requests)

    Server Errors:
        - Internal server error (500)
        - Service unavailable (503)

    Network Errors:
        - Connection timeout
        - DNS resolution failure
        - Network unreachable

  Error Response Structure
    API errors are converted to PowerShell ErrorRecords with:

    Exception Message:
        Human-readable error description

    CategoryInfo:
        PowerShell error category (AuthenticationError, InvalidData, etc.)

    TargetObject:
        Original API response for detailed inspection

    ErrorDetails:
        Structured error information from API

  HTTP Status Code Mapping
    The module maps HTTP status codes to PowerShell error categories:

    400 Bad Request → InvalidData
    401 Unauthorized → AuthenticationError
    403 Forbidden → PermissionDenied
    404 Not Found → ObjectNotFound
    422 Unprocessable → InvalidData
    429 Too Many Requests → LimitsExceeded
    500 Server Error → InvalidOperation
    503 Service Unavailable → ConnectionError

  Try-Catch Error Handling
    Use try-catch blocks to handle errors gracefully:

    try {
        $employee = Get-UKGEmployee -Id "emp123"
    }
    catch {
        Write-Warning "Failed to get employee: $($_.Exception.Message)"
    }

    Specific Error Handling:
        try {
            Connect-UKG -ApplicationId "app" -ApplicationSecret $secret -ClientId "client"
        }
        catch [System.Net.WebException] {
            Write-Error "Network error: Cannot reach UKG API"
        }
        catch {
            Write-Error "Authentication failed: $($_.Exception.Message)"
        }

  ErrorAction Parameter
    Control error behavior with -ErrorAction:

    Stop:
        Halt execution on error (default for cmdlets)

        Get-UKGEmployee -Id "invalid" -ErrorAction Stop

    Continue:
        Display error and continue execution

        Get-UKGEmployee -Id "invalid" -ErrorAction Continue

    SilentlyContinue:
        Suppress error display and continue

        $employee = Get-UKGEmployee -Id "invalid" -ErrorAction SilentlyContinue
        if (-not $employee) {
            Write-Host "Employee not found"
        }

    Inquire:
        Prompt user for action on error

  Error Variables
    PowerShell automatic error variables:

    $Error:
        Array of all errors in current session
        $Error[0] is most recent error

    $?:
        Boolean indicating success of last command
        $true if successful, $false if error

    $LASTEXITCODE:
        Exit code of last external program (not used by module)

  Verbose and Debug Output
    Enable detailed logging for troubleshooting:

    Verbose Output (-Verbose):
        Shows detailed operation information
        Includes API URLs, HTTP methods, pagination info

        Get-UKGEmployee -All -Verbose

    Debug Output (-Debug):
        Shows detailed debugging information
        Prompts before continuing (can be suppressed with -Debug:$false)

        Connect-UKG -ApplicationId "app" -ApplicationSecret $secret -ClientId "client" -Debug

    Set Module-Wide Verbosity:
        $VerbosePreference = "Continue"
        $DebugPreference = "Continue"

        # All cmdlets will now show verbose/debug output
        Get-UKGEmployee -All

        # Reset
        $VerbosePreference = "SilentlyContinue"
        $DebugPreference = "SilentlyContinue"

  Common Error Scenarios
    Connection Required:
        Error: "No active UKG session. Use Connect-UKG first."
        Solution: Call Connect-UKG before other cmdlets.

        Connect-UKG -ApplicationId "app" -ApplicationSecret $secret -ClientId "client"
        Get-UKGEmployee -All

    Invalid Credentials:
        Error: "401 Unauthorized: Invalid client credentials"
        Solution: Verify ApplicationId, ApplicationSecret, and ClientId.

    Resource Not Found:
        Error: "404 Not Found: Employee not found"
        Solution: Verify the resource ID exists. Use Search or List operations
                 to find correct IDs.

        # Check if employee exists first
        $employee = Get-UKGEmployee -Id "emp123" -ErrorAction SilentlyContinue
        if ($employee) {
            # Update employee
            Set-UKGEmployee -Id "emp123" -Title "Manager"
        } else {
            Write-Warning "Employee emp123 not found"
        }

    Validation Error:
        Error: "400 Bad Request: Validation failed"
        Solution: Check the error details for specific field issues.

        try {
            New-UKGEmployee -Email "invalid-email" -FirstName "John" -LastName "Doe"
        }
        catch {
            $details = $_.ErrorDetails.Message | ConvertFrom-Json
            Write-Host "Validation errors:"
            $details.errors | ForEach-Object {
                Write-Host " $($_.field): $($_.message)"
            }
        }

    Rate Limiting:
        Error: "429 Too Many Requests"
        Solution: Implement retry logic with exponential backoff.

        $maxRetries = 3
        $retryCount = 0
        $success = $false

        while (-not $success -and $retryCount -lt $maxRetries) {
            try {
                $employee = Get-UKGEmployee -Id "emp123"
                $success = $true
            }
            catch {
                if ($_.Exception.Response.StatusCode -eq 429) {
                    $retryCount++
                    $delay = [Math]::Pow(2, $retryCount)
                    Write-Warning "Rate limited. Retrying in $delay seconds..."
                    Start-Sleep -Seconds $delay
                } else {
                    throw
                }
            }
        }

  Logging Errors
    Log errors for audit and troubleshooting:

    # Simple error log
    try {
        Get-UKGEmployee -Id "emp123"
    }
    catch {
        $errorLog = [PSCustomObject]@{
            Timestamp = Get-Date
            Cmdlet = "Get-UKGEmployee"
            Error = $_.Exception.Message
            Details = $_.ErrorDetails.Message
        }
        $errorLog | Export-Csv -Path "ukg_errors.csv" -Append -NoTypeInformation
        throw
    }

  Debugging Techniques
    Inspect Error Details:
        $Error[0] | Format-List * -Force
        $Error[0].Exception | Format-List * -Force

    View API Response:
        Many errors include TargetObject with full API response:

        try {
            New-UKGEmployee -Email "test@test.com" -FirstName "Test"
        }
        catch {
            $_.TargetObject # Contains API response
        }

    Enable Verbose Logging:
        $VerbosePreference = "Continue"
        Get-UKGEmployee -Id "emp123"

    Check Session Status:
        $session = Get-UKGSession
        $session | Format-List *

  Testing Error Scenarios
    Staging Environment:
        Test error handling in staging before production:

        Connect-UKG -ApplicationId "app" -ApplicationSecret $secret `
                    -ClientId "client" -Region EU -Environment Staging

    WhatIf Parameter:
        Preview changes without executing (for cmdlets that support it):

        Set-UKGEmployee -Id "emp123" -Title "Manager" -WhatIf

    Confirm Parameter:
        Require confirmation before state-changing operations:

        Remove-UKGEmployee -Id "emp123" -Confirm

  Best Practices
    1. Always Use Try-Catch for Critical Operations:
        Wrap important operations in error handling.

    2. Check Return Values:
        Verify cmdlet results before proceeding.

        $employee = Get-UKGEmployee -Id "emp123" -ErrorAction SilentlyContinue
        if ($employee) {
            # Proceed
        }

    3. Log Errors:
        Maintain error logs for troubleshooting.

    4. Use Verbose Output During Development:
        Enable -Verbose to understand what the module is doing.

    5. Test in Staging:
        Validate scripts in staging before running in production.

    6. Implement Retry Logic for Network Errors:
        Transient network issues should be retried.

    7. Validate Input Data:
        Check data before sending to API to avoid validation errors.

EXAMPLES
  Example 1: Basic Error Handling
    # Handle employee not found
    try {
        $employee = Get-UKGEmployee -Id "emp123"
        Write-Host "Found: $($employee.email)"
    }
    catch {
        Write-Warning "Employee not found or other error: $($_.Exception.Message)"
    }

  Example 2: Specific Error Category Handling
    # Handle different error types differently
    try {
        $employee = New-UKGEmployee -Email "test@test.com" -FirstName "Test" -LastName "User"
    }
    catch [Microsoft.PowerShell.Commands.HttpResponseException] {
        $statusCode = $_.Exception.Response.StatusCode.value__

        switch ($statusCode) {
            400 {
                Write-Error "Validation error: $($_.ErrorDetails.Message)"
            }
            401 {
                Write-Error "Authentication failed. Check credentials."
            }
            403 {
                Write-Error "Permission denied. Check role permissions."
            }
            429 {
                Write-Warning "Rate limited. Retry later."
            }
            default {
                Write-Error "Unexpected error: $($_.Exception.Message)"
            }
        }
    }

  Example 3: Retry Logic with Exponential Backoff
    # Retry on transient errors
    function Invoke-WithRetry {
        param(
            [ScriptBlock]$ScriptBlock,
            [int]$MaxRetries = 3
        )

        $retryCount = 0
        while ($retryCount -lt $MaxRetries) {
            try {
                & $ScriptBlock
                return
            }
            catch {
                $retryCount++
                if ($retryCount -ge $MaxRetries) {
                    throw
                }

                $delay = [Math]::Pow(2, $retryCount)
                Write-Warning "Attempt $retryCount failed. Retrying in $delay seconds..."
                Start-Sleep -Seconds $delay
            }
        }
    }

    # Use retry wrapper
    Invoke-WithRetry {
        $employee = Get-UKGEmployee -Id "emp123"
    }

  Example 4: Validation Before API Call
    # Validate data before creating employee
    $email = "newemployee@company.com"
    $firstName = "John"
    $lastName = "Doe"

    # Validate email format
    if ($email -notmatch "^[\w\.-]+@[\w\.-]+\.\w+$") {
        Write-Error "Invalid email format: $email"
        return
    }

    # Validate required fields
    if ([string]::IsNullOrWhiteSpace($firstName) -or [string]::IsNullOrWhiteSpace($lastName)) {
        Write-Error "First name and last name are required"
        return
    }

    # Proceed with API call
    try {
        New-UKGEmployee -Email $email -FirstName $firstName -LastName $lastName
    }
    catch {
        Write-Error "Failed to create employee: $($_.Exception.Message)"
    }

  Example 5: Comprehensive Error Logging
    # Log errors with full context
    function Invoke-UKGWithLogging {
        param(
            [ScriptBlock]$ScriptBlock,
            [string]$Operation
        )

        try {
            & $ScriptBlock
        }
        catch {
            $errorEntry = [PSCustomObject]@{
                Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
                Operation = $Operation
                Error = $_.Exception.Message
                StatusCode = $_.Exception.Response.StatusCode.value__
                ErrorDetails = $_.ErrorDetails.Message
                StackTrace = $_.ScriptStackTrace
            }

            # Log to file
            $errorEntry | Export-Csv -Path "ukg_errors.csv" -Append -NoTypeInformation

            # Re-throw for caller to handle
            throw
        }
    }

    # Use logging wrapper
    Invoke-UKGWithLogging -Operation "Get Employee" {
        Get-UKGEmployee -Id "emp123"
    }

  Example 6: Verbose Debugging Session
    # Enable verbose output for troubleshooting
    $VerbosePreference = "Continue"

    Connect-UKG -ApplicationId "app" -ApplicationSecret $secret -ClientId "client" -Region EU -Verbose
    # Shows: Token URL, authentication details

    Get-UKGEmployee -Id "emp123" -Verbose
    # Shows: API URL, HTTP method, response status

    $VerbosePreference = "SilentlyContinue"

  Example 7: Graceful Degradation
    # Try to get employee, fall back to search if not found
    $employeeId = "emp123"

    $employee = Get-UKGEmployee -Id $employeeId -ErrorAction SilentlyContinue

    if (-not $employee) {
        Write-Warning "Employee $employeeId not found. Searching by email..."

        $email = "employee@company.com"
        $results = Search-UKGEmployee -Email $email -ErrorAction SilentlyContinue

        if ($results) {
            $employee = $results[0]
            Write-Host "Found employee via search: $($employee.id)"
        } else {
            Write-Error "Employee not found by ID or email"
            return
        }
    }

    # Proceed with employee object
    Write-Host "Employee: $($employee.first_name) $($employee.last_name)"

KEYWORDS
    Error, Exception, Try, Catch, Verbose, Debug, Troubleshooting

SEE ALSO
    about_PSUKG
    about_CommonParameters
    about_Try_Catch_Finally
    Get-UKGSession