public/Start-UnraidArray.ps1

function Start-UnraidArray {
    <#
    .SYNOPSIS
        Starts the Unraid array.

    .DESCRIPTION
        Initiates a start of the Unraid array via the GraphQL API.
        
        LIMITATION:
        This function CANNOT unlock encrypted arrays. The Unraid 7.0 API does not
        currently accept encryption keys or passphrases during the start operation.
        If your array is encrypted and locked, you must unlock it via the WebUI.

    .PARAMETER Array
        An object representing the current array state.

    .PARAMETER Session
        The active Unraid session.

    .PARAMETER WaitTimeout
        Seconds to wait for the array to reach the STARTED state.

    .PARAMETER Force
        Sends the start command even if the API reports the array is already started.
        Useful for recovering from 'stuck' states caused by unsynced API.
    #>

    [CmdletBinding(SupportsShouldProcess)]
    [OutputType('String')]
    param(
        [Parameter(ValueFromPipeline)]
        [psobject]$Array,

        [Parameter()]
        [UnraidSession]$Session = $script:DefaultUnraidSession,

        [Parameter()]
        [int]$WaitTimeout = 120,

        [Parameter()]
        [switch]$Force
    )

    process {
        if (!$Array) {
            Write-Verbose "Checking status..."
            $Array = Get-UnraidArray -Session $Session
        }

        # Check for unsynced state (Started but unmounted - caused by API issue) or standard Started state
        if ($Array.State -match "STARTED") {
            if ($Force) { Write-Verbose "Array is '$($Array.State)', but -Force was used. Proceeding..." }
            else {
                if ($Array.State -like "*UNMOUNTED*") {
                    Write-Warning "Array reports 'STARTED' but is unmounted (0 capacity). The API is likely not synced to the current server state.`nYou likely need to run 'Restart-UnraidApi' to reset the state, then rerun this command."
                }
                else { Write-Warning "The Unraid array is already in the 'STARTED' state." }
                return
            }
        }

        if ($PSCmdlet.ShouldProcess("Unraid Array", "Start array")) {
            
            $gqlQuery = @"
            mutation SetArrayState {
                array {
                    setState(input: { desiredState: START }) {
                        state
                    }
                }
            }
"@

            $commandSent = $false

            try {
                Write-Verbose "Sending start mutation..."
                $result = Invoke-UnraidQuery -Query $gqlQuery -Session $Session
                
                $commandSent = $true
                $currentState = $result.array.setState.state
            }
            catch {
                $ex = $_.Exception
                
                # Check for "already started" state
                if ($ex.Message -match "already STARTED") {
                    $verify = Get-UnraidArray -Session $Session
                    if ($verify.TotalSize -eq "0 B") {
                        Write-Error "API returns STARTED, but API may be unsynced.`nRun 'Stop-UnraidArray -Force' to force stop."
                        return
                    }
                    Write-Information "Array is already STARTED." -InformationAction Continue
                    return
                }
                # Handle API limitation for Encryption
                elseif ($ex.Message -match "passphrase" -or $ex.Message -match "encrypted" -or $ex.Message -match "key") {
                    Write-Error "Start Failed: The array requires an encryption key, but the Unraid API does not support unlocking arrays yet.`nPlease unlock the array via the WebUI."
                    return
                }
                # Handle Timeouts
                elseif ($ex.Message -match "504" -or ($ex.Response -and $ex.Response.StatusCode -eq 504)) {
                    Write-Warning "Server timed out (504) waiting for start. Switching to polling mode."
                    $commandSent = $true
                    $currentState = "UNKNOWN"
                }
                else { $PSCmdlet.ThrowTerminatingError($_) }
            }

            if ($commandSent) {
                $timer = [System.Diagnostics.Stopwatch]::StartNew()
                
                while ($currentState -ne "STARTED" -and $timer.Elapsed.TotalSeconds -lt $WaitTimeout) {
                    $remaining = $WaitTimeout - [int]$timer.Elapsed.TotalSeconds
                    Write-Progress -Activity "Starting Unraid Array" -Status "Current State: $currentState" -SecondsRemaining $remaining
                    
                    Start-Sleep -Seconds 5
                    
                    try {
                        $statusCheck = Get-UnraidArray -Session $Session
                        $currentState = $statusCheck.State
                    }
                    catch {  Write-Verbose "Poll failed: $($_.Exception.Message)" }
                }
                
                $timer.Stop()
                Write-Progress -Activity "Starting Unraid Array" -Completed

                if ($currentState -eq "STARTED") { Write-Information "Array started." -InformationAction Continue  }
                else { Write-Error "Timed out waiting for start ($WaitTimeout s). Current state: $currentState" }
            }
        }
    }
}