LangStream / langstream

LangStream. Event-Driven Developer Platform for Building and Running LLM AI Apps. Powered by Kubernetes and Kafka.
https://langstream.ai
Apache License 2.0
379 stars 28 forks source link

Langstream CLI tool fails if ${HOME}/.langstream is a symlink instead of a directory #697

Closed Gagravarr closed 8 months ago

Gagravarr commented 8 months ago

Following https://github.com/LangStream/langstream#installation for Unix, the script creates a folder ${HOME}/.langstream

If you leave that folder alone, then the langstream tool runs without error

However, if you want to have langstream somewhere else and you move the folder + symlink it back (eg you move it onto a different disk), such as with

mv .langstream /data/langstream
ln -s /data/langstream/ .langstream

Then when you try to run the langstream tool again, it fails because it tries to re-create the .langstream directory which is now a symlink

Full stacktrace of the error is:

Exception in thread "main" picocli.CommandLine$InitializationException: Could not inject spec
    at picocli.CommandLine$Model$CommandReflection.initFromAnnotatedTypedMembers(CommandLine.java:11975)
    at picocli.CommandLine$Model$CommandReflection.initFromAnnotatedMembers(CommandLine.java:11909)
    at picocli.CommandLine$Model$CommandReflection.extractCommandSpec(CommandLine.java:11842)
    at picocli.CommandLine$Model$CommandSpec.forAnnotatedObject(CommandLine.java:6388)
    at picocli.CommandLine.<init>(CommandLine.java:230)
    at picocli.CommandLine.toCommandLine(CommandLine.java:3631)
    at picocli.CommandLine.access$16700(CommandLine.java:148)
    at picocli.CommandLine$Model$CommandReflection.initSubcommands(CommandLine.java:11874)
    at picocli.CommandLine$Model$CommandReflection.extractCommandSpec(CommandLine.java:11840)
    at picocli.CommandLine$Model$CommandSpec.forAnnotatedObject(CommandLine.java:6388)
    at picocli.CommandLine.<init>(CommandLine.java:230)
    at picocli.CommandLine.toCommandLine(CommandLine.java:3631)
    at picocli.CommandLine.access$16700(CommandLine.java:148)
    at picocli.CommandLine$Model$CommandReflection.initSubcommands(CommandLine.java:11874)
    at picocli.CommandLine$Model$CommandReflection.extractCommandSpec(CommandLine.java:11840)
    at picocli.CommandLine$Model$CommandSpec.forAnnotatedObject(CommandLine.java:6388)
    at picocli.CommandLine.<init>(CommandLine.java:230)
    at picocli.CommandLine.<init>(CommandLine.java:224)
    at picocli.CommandLine.<init>(CommandLine.java:199)
    at ai.langstream.cli.LangStreamCLI.execute(LangStreamCLI.java:46)
    at ai.langstream.cli.LangStreamCLI.main(LangStreamCLI.java:41)
Caused by: picocli.CommandLine$PicocliException: Could not get scope for field protected picocli.CommandLine$Model$CommandSpec ai.langstream.cli.commands.BaseCmd.command
    at picocli.CommandLine$Model$FieldBinding.set(CommandLine.java:12108)
    ... 21 more
Caused by: picocli.CommandLine$InitializationException: Could not instantiate class ai.langstream.cli.commands.archetypes.ListArchetypesCmd: java.lang.reflect.InvocationTargetException
    at picocli.CommandLine$DefaultFactory.create(CommandLine.java:5687)
    at picocli.CommandLine$Model$CommandUserObject.getInstance(CommandLine.java:12263)
    at picocli.CommandLine$Model$CommandUserObject.get(CommandLine.java:12288)
    at picocli.CommandLine$Model$FieldBinding.set(CommandLine.java:12107)
    ... 21 more
Caused by: java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
    at picocli.CommandLine$DefaultFactory.create(CommandLine.java:5658)
    at picocli.CommandLine$DefaultFactory.create(CommandLine.java:5683)
    ... 24 more
Caused by: java.nio.file.FileAlreadyExistsException: /home/nick/.langstream
    at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:94)
    at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106)
    at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
    at java.base/sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:397)
    at java.base/java.nio.file.Files.createDirectory(Files.java:700)
    at java.base/java.nio.file.Files.createAndCheckIsDirectory(Files.java:807)
    at java.base/java.nio.file.Files.createDirectories(Files.java:753)
    at ai.langstream.cli.LangStreamCLI.getLangstreamCLIHomeDirectory(LangStreamCLI.java:34)
    at ai.langstream.cli.commands.BaseCmd.<init>(BaseCmd.java:124)
    at ai.langstream.cli.commands.archetypes.BaseArchetypeCmd.<init>(BaseArchetypeCmd.java:23)
    at ai.langstream.cli.commands.archetypes.ListArchetypesCmd.<init>(ListArchetypesCmd.java:24)
    ... 31 more

The code in question seems to be https://github.com/LangStream/langstream/blob/main/langstream-cli/src/main/java/ai/langstream/cli/LangStreamCLI.java#L35

Which appears to be triggering this long standing "won't fix" - https://bugs.openjdk.org/browse/JDK-8130464

I believe either the getLangstreamCLIHomeDirectory method should be updated to check for symlinks too, or it should be possible to pass in an environment variable to point the tool at a different (non-symlink) directory. Or maybe both!

eolivelli commented 8 months ago

Good catch... Would you please send a fix?