@@ -172,6 +172,7 @@ var Init = func(args []string, stdin io.Reader) (*global.Data, error) {
172172 ConfigPath : config .FilePath ,
173173 Env : e ,
174174 ErrLog : fsterr .Log ,
175+ ErrOutput : os .Stderr ,
175176 ExecuteWasmTools : compute .ExecuteWasmTools ,
176177 HTTPClient : httpClient ,
177178 Manifest : & md ,
@@ -200,9 +201,11 @@ func Exec(data *global.Data) error {
200201 return err
201202 }
202203
203- // Check for --json flag early and set quiet mode if found.
204+ // Check for --json flag early. JSON mode suppresses stdout-bound noise
205+ // (metadata notices, update checks) but still allows stderr warnings
206+ // (token expiry, profile mismatch) so they don't corrupt JSON output.
204207 if slices .Contains (data .Args , "--json" ) {
205- data .Flags .Quiet = true
208+ data .Flags .JSON = true
206209 }
207210
208211 // We short-circuit the execution for specific cases:
@@ -219,7 +222,7 @@ func Exec(data *global.Data) error {
219222 }
220223
221224 metadataDisable , _ := strconv .ParseBool (data .Env .WasmMetadataDisable )
222- if ! slices .Contains (data .Args , "--metadata-disable" ) && ! metadataDisable && ! data .Config .CLI .MetadataNoticeDisplayed && commandCollectsData (commandName ) && ! data .Flags .Quiet {
225+ if ! slices .Contains (data .Args , "--metadata-disable" ) && ! metadataDisable && ! data .Config .CLI .MetadataNoticeDisplayed && commandCollectsData (commandName ) && ! data .Flags .Quiet && ! data . Flags . JSON {
223226 text .Important (data .Output , "The Fastly CLI is configured to collect data related to Wasm builds (e.g. compilation times, resource usage, and other non-identifying data). To learn more about what data is being collected, why, and how to disable it: https://www.fastly.com/documentation/reference/cli" )
224227 text .Break (data .Output )
225228 data .Config .CLI .MetadataNoticeDisplayed = true
@@ -230,7 +233,7 @@ func Exec(data *global.Data) error {
230233 time .Sleep (5 * time .Second ) // this message is only displayed once so give the user a chance to see it before it possibly scrolls off screen
231234 }
232235
233- if data .Flags .Quiet {
236+ if data .Flags .Quiet || data . Flags . JSON {
234237 data .Manifest .File .SetQuiet (true )
235238 }
236239
@@ -287,9 +290,9 @@ func Exec(data *global.Data) error {
287290 if ! data .Flags .Quiet && data .Flags .Token == "" && data .Env .APIToken == "" && data .Manifest != nil && data .Manifest .File .Profile != "" {
288291 if data .Config .GetAuthToken (data .Manifest .File .Profile ) == nil {
289292 if defaultName , _ := data .Config .GetDefaultAuthToken (); defaultName != "" {
290- text .Warning (data .Output , "fastly.toml profile %q not found in auth config, using default token %q.\n " , data .Manifest .File .Profile , defaultName )
293+ text .Warning (data .ErrOutput , "fastly.toml profile %q not found in auth config, using default token %q.\n " , data .Manifest .File .Profile , defaultName )
291294 } else {
292- text .Warning (data .Output , "fastly.toml profile %q not found in auth config and no default token is configured.\n " , data .Manifest .File .Profile )
295+ text .Warning (data .ErrOutput , "fastly.toml profile %q not found in auth config and no default token is configured.\n " , data .Manifest .File .Profile )
293296 }
294297 }
295298 }
@@ -316,7 +319,7 @@ func Exec(data *global.Data) error {
316319 displayToken (tokenSource , data )
317320 }
318321 if ! data .Flags .Quiet {
319- checkConfigPermissions (tokenSource , data .Output )
322+ checkConfigPermissions (tokenSource , data .ErrOutput )
320323 }
321324
322325 data .APIClient , data .RTSClient , err = configureClients (token , apiEndpoint , data .APIClientFactory , data .Flags .Debug )
@@ -328,7 +331,7 @@ func Exec(data *global.Data) error {
328331
329332 checkTokenExpirationWarning (data , commandName )
330333
331- f := checkForUpdates (data .Versioners .CLI , commandName , data .Flags .Quiet )
334+ f := checkForUpdates (data .Versioners .CLI , commandName , data .Flags .Quiet || data . Flags . JSON )
332335 defer f (data .Output )
333336
334337 return command .Exec (data .Input , data .Output )
@@ -506,9 +509,10 @@ func checkAndRefreshAuthSSOToken(name string, at *config.AuthToken, data *global
506509// This matches the set hidden by FASTLY_DISABLE_AUTH_COMMAND (pkg/env/env.go).
507510var authRelatedCommands = []string {"auth" , "auth-token" , "sso" , "profile" , "whoami" }
508511
509- // checkTokenExpirationWarning prints a warning if the active stored token is
510- // about to expire. Only fires for SourceAuth tokens; env/flag tokens are opaque.
511- // Suppressed for auth-related commands and when --quiet or --json is active.
512+ // checkTokenExpirationWarning prints a warning to stderr if the active stored
513+ // token is about to expire. Only fires for SourceAuth tokens; env/flag tokens
514+ // are opaque. Suppressed for auth-related commands and when --quiet is active.
515+ // In --json mode the warning still fires (written to stderr via data.ErrOutput).
512516func checkTokenExpirationWarning (data * global.Data , commandName string ) {
513517 if data .Flags .Quiet {
514518 return
@@ -545,7 +549,7 @@ func checkTokenExpirationWarning(data *global.Data, commandName string) {
545549 if at .RefreshExpiresAt != "" {
546550 label = "session "
547551 }
548- text .Warning (data .Output , "Your active token %s%s. %s\n " , label , summary , remediation )
552+ text .Warning (data .ErrOutput , "Your active token %s%s. %s\n " , label , summary , remediation )
549553}
550554
551555// isAuthRelatedCommand reports whether commandName belongs to an auth-related
0 commit comments