Skip to content

Commit 32b1386

Browse files
committed
fix: catch AuthError to an informative message
Before, ```console % AWS_PROFILE=x stack exec -- stackctl cat CredentialChainExhausted ``` Now, ```console % AWS_PROFILE=x stack exec -- stackctl cat 2025-10-17 18:31:44 [error ] No AWS credentials were found in your environment. For details of where stackctl looks for credentials, see: https://hackage.haskell.org/package/amazonka-2.0/docs/Amazonka-Auth.html#v:discover exception=CredentialChainExhausted ```
1 parent 8537f46 commit 32b1386

2 files changed

Lines changed: 26 additions & 3 deletions

File tree

src/Stackctl/AWS/Core.hs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module Stackctl.AWS.Core
1212
, withAssumedRole
1313

1414
-- * Error-handling
15+
, handlingAuthError
1516
, handlingServiceError
1617
, formatServiceError
1718

@@ -38,6 +39,7 @@ import Amazonka
3839
, serviceError_code
3940
, serviceError_message
4041
, serviceError_requestId
42+
, _AuthError
4143
, _Sensitive
4244
, _ServiceError
4345
)
@@ -49,6 +51,7 @@ import qualified Amazonka.Env as Amazonka
4951
import Amazonka.STS.AssumeRole
5052
import Control.Monad.AWS
5153
import Control.Monad.Logger (defaultLoc, toLogStr)
54+
import qualified Data.Text as T
5255
import Data.Typeable (typeRep)
5356
import Stackctl.AWS.Orphans ()
5457
import UnliftIO.Exception.Lens (handling)
@@ -149,6 +152,22 @@ newtype AccountId = AccountId
149152
}
150153
deriving newtype (Eq, Ord, Show, ToJSON)
151154

155+
-- | Handle 'AuthError', log it and 'exitFailure'
156+
handlingAuthError :: (MonadUnliftIO m, MonadLogger m) => m a -> m a
157+
handlingAuthError =
158+
handling _AuthError $ \e -> do
159+
logError $ msg :# ["exception" .= displayException e]
160+
exitFailure
161+
where
162+
msg =
163+
"No AWS credentials were found in your environment."
164+
<> continuation "For details of where stackctl looks for credentials, see:"
165+
<> continuation
166+
"https://hackage.haskell.org/package/amazonka-2.0/docs/Amazonka-Auth.html#v:discover"
167+
168+
-- Shift the continuation lines to line up with the first message line
169+
continuation x = "\n" <> T.replicate 32 " " <> x
170+
152171
-- | Handle 'ServiceError', log it and 'exitFailure'
153172
--
154173
-- This is useful at the top-level of the app, where we'd be crashing anyway. It

src/Stackctl/CLI.hs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Control.Monad.AWS as AWS
1313
import Control.Monad.AWS.ViaReader as AWS
1414
import Control.Monad.Catch (MonadCatch)
1515
import Control.Monad.Trans.Resource (MonadResource, ResourceT, runResourceT)
16+
import Stackctl.AWS.Core (handlingAuthError)
1617
import qualified Stackctl.AWS.Core as AWS
1718
import Stackctl.AWS.Scope
1819
import Stackctl.AutoSSO
@@ -103,9 +104,12 @@ runAppT options f = do
103104
envLogSettings
104105

105106
withLogger logSettings $ \appLogger -> do
106-
appAwsEnv <- runWithLogger appLogger $ handleAutoSSO options $ do
107-
logDebug "Discovering AWS credentials"
108-
AWS.discover
107+
appAwsEnv <- runWithLogger appLogger
108+
$ handleAutoSSO options
109+
$ handlingAuthError
110+
$ do
111+
logDebug "Discovering AWS credentials"
112+
AWS.discover
109113
appConfig <- runWithLogger appLogger loadConfigOrExit
110114
appAwsScope <- AWS.runEnvT fetchAwsScope appAwsEnv
111115

0 commit comments

Comments
 (0)