Docker up.ps1, a Sitecore CLI empty user.json and a bored developer

This blog post is about a rogue error I faced while doing up.ps1 while working with the Docker JSS setup. Since this deals with Sitecore CLI user.json creation, first stick to basics and remind ourselves of the Sitecore CLI process flow through a diagram.

Sitecore CLI user.json creation process flow:


In a Docker setup, traefik exposes the Sitecore CM instance so, if traefik is unable to make the REST call, https connection to CM will fail with blank user details returned but file could still be created in the file system:


traefik - CM invocation in up.ps1:


Another view:


Error:

File C:\jss\scnextjs\.sitecore\user.json is empty

C:\jss\scnextjs\up.ps1 : Unable to log into Sitecore, did the Sitecore environment start correctly? See logs above.

At line:1 char:1

+ .\up.ps1

+ ~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException

    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,up.ps1



Context:

During one of my routine Docker up.ps1 executions, I had the following issue: 

user.json file was created but empty:


I understand that there is usually an expired token that is usually thrown but this was bizarre and seemed one-off.

Any further runs of up.ps1 was unable to proceed and failed exactly at the same point of bringing up the ID instance since the flow assumed that a valid user.json is present.

What to do?

Simplest approach: Since the file should automatically be regenerated, just delete the file manually, execute up.ps1, be a good samaritan, enter credentials on time to see user.json get created as per plan and wish everything goes fine this time:


When would traefik fail to connect to the CM instance is another issue to analyse though!

If you love to complicate:

Although I could deduce that this issue is because there is no transaction block in the PowerShell script to commit or abort the file creation process as a whole and it is not possible in this case since Docker connects to CM through an external REST call, 

I just wanted to keep it simple as well as minimise the impact through code so, modified up.ps1: delete the user.json if ever the file is empty. This way, the execution is not blocked during further runs. 

Issue root-cause: Wrong assumption:


if ([String]::IsNullOrWhiteSpace((Get-content .\.sitecore\user.json -ErrorAction SilentlyContinue)) -eq $True) {Remove-Item .\.sitecore\user.json -ErrorAction SilentlyContinue}



Note: Add the line before Write-Error since the latter exits the code right away without executing further lines 

If you want to play it safe, can be added outside the file creation process and that is the reason SilentlyContinue is useful:

End-result: the file will be deleted if ever it is blank and up.ps1 will now be able to regenerate the file without any hiccups.

Further Note

The below exception is the same scenario as above but you run the command through CLI with an empty user.json:

dotnet sitecore login --authority <id instance> --cm <cm instance> --allow-write true

Resolution: Just delete the user.json and run the command to regenerate the file


Unhandled exception: System.Exception: Unhandled exception

 ---> System.NullReferenceException: Object reference not set to an instance of an object.

   at Sitecore.DevEx.Configuration.FilesystemConfigurationManager.ReadRootConfiguration(Stream rootConfigurationStream, Stream userConfigurationStream, String filePath) in C:\BA\ca7111d945a16af4\src\Sitecore.DevEx.Configuration\FilesystemConfigurationManager.cs:line 80

   at Sitecore.DevEx.Configuration.FilesystemConfigurationManager.ReadRootConfiguration(String rootConfigurationPath) in C:\BA\ca7111d945a16af4\src\Sitecore.DevEx.Configuration\FilesystemConfigurationManager.cs:line 60

   at Sitecore.DevEx.Client.Tasks.LoginTask.Execute(LoginTaskOptions options) in C:\BA\ca7111d945a16af4\src\Sitecore.DevEx.Client\Tasks\LoginTask.cs:line 32

   at Sitecore.DevEx.Client.Cli.Subcommands.LoginCommand.Handle(LoginTask task, LoginArgs args) in C:\BA\ca7111d945a16af4\src\Sitecore.DevEx.Client.Cli\Subcommands\LoginCommand.cs:line 33

   at Sitecore.Devex.Client.Cli.Extensibility.Subcommands.SubcommandBase`2.HandleInternal(TArgs args) in C:\BA\ca7111d945a16af4\src\Sitecore.Devex.Client.Cli.Extensibility\Subcommands\SubcommandBase.cs:line 75

   --- End of inner exception stack trace ---

   at Sitecore.Devex.Client.Cli.Extensibility.Subcommands.SubcommandBase`2.HandleExceptionMessageConsoleLogging(Exception exception, ILogger logger) in C:\BA\ca7111d945a16af4\src\Sitecore.Devex.Client.Cli.Extensibility\Subcommands\SubcommandBase.cs:line 118

   at Sitecore.Devex.Client.Cli.Extensibility.Subcommands.SubcommandBase`2.HandleInternal(TArgs args) in C:\BA\ca7111d945a16af4\src\Sitecore.Devex.Client.Cli.Extensibility\Subcommands\SubcommandBase.cs:line 81

   at System.CommandLine.Invocation.CommandHandler.GetResultCodeAsync(Object value, InvocationContext context)

   at System.CommandLine.Invocation.ModelBindingCommandHandler.InvokeAsync(InvocationContext context)

   at System.CommandLine.Invocation.InvocationPipeline.<>c__DisplayClass4_0.<<BuildInvocationChain>b__0>d.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseParseErrorReporting>b__20_0>d.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass15_0.<<UseHelp>b__0>d.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass24_0.<<UseVersionOption>b__0>d.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass22_0.<<UseTypoCorrections>b__0>d.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseSuggestDirective>b__21_0>d.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseParseDirective>b__19_0>d.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseDebugDirective>b__11_0>d.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<RegisterWithDotnetSuggest>b__10_0>d.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass13_0.<<UseExceptionHandler>b__0>d.MoveNext()


Comments