Skip to content

Neo4jVectorStore doAdd method ignores sessionConfig #5191

@Fenriel

Description

@Fenriel

Bug description
When calling vectorStore.add() method and configuring Neo4jVectorStore with a custom database name (e.g., "my-db-name"), the store still attempts to connect to the default "neo4j" database, causing connection failures when the specified database doesn't exist.

Error Stack Trace

org.neo4j.driver.exceptions.FatalDiscoveryException: Unable to get a routing table for database 'neo4j' because this database does not exist

	at org.neo4j.driver.internal.util.Futures.blockingGet(Futures.java:63)
	at org.neo4j.driver.internal.InternalSession.beginTransaction(InternalSession.java:202)
	at org.neo4j.driver.internal.InternalSession.lambda$transaction$5(InternalSession.java:176)
	at org.neo4j.driver.internal.retry.ExponentialBackoffRetryLogic.retry(ExponentialBackoffRetryLogic.java:114)
	at org.neo4j.driver.internal.InternalSession.transaction(InternalSession.java:175)
	at org.neo4j.driver.internal.InternalSession.execute(InternalSession.java:160)
	at org.neo4j.driver.internal.InternalSession.executeWrite(InternalSession.java:132)
	at org.neo4j.driver.Session.executeWrite(Session.java:169)
	at org.springframework.ai.vectorstore.neo4j.Neo4jVectorStore.doAdd(Neo4jVectorStore.java:221)
	at org.springframework.ai.vectorstore.observation.AbstractObservationVectorStore.lambda$add$1(AbstractObservationVectorStore.java:85)
	at io.micrometer.observation.Observation.observe(Observation.java:498)
	at org.springframework.ai.vectorstore.observation.AbstractObservationVectorStore.add(AbstractObservationVectorStore.java:85)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	Suppressed: org.neo4j.driver.internal.util.ErrorUtil$InternalExceptionCause
		at org.neo4j.driver.internal.adaptedbolt.ErrorMapper.mapToNeo4jException(ErrorMapper.java:224)
		at org.neo4j.driver.internal.adaptedbolt.ErrorMapper.mapBoltFailureException(ErrorMapper.java:137)
		at org.neo4j.driver.internal.adaptedbolt.ErrorMapper.map(ErrorMapper.java:81)
		at org.neo4j.driver.internal.adaptedbolt.ErrorMapper.mapAndThrow(ErrorMapper.java:66)
		at java.base/java.util.concurrent.CompletableFuture.uniExceptionally(CompletableFuture.java:990)
		at java.base/java.util.concurrent.CompletableFuture$UniExceptionally.tryFire(CompletableFuture.java:974)
		at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
		at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2162)
		at org.neo4j.bolt.connection.routed.impl.cluster.RoutingTableRegistryImpl.lambda$ensureDatabaseNameIsCompleted$6(RoutingTableRegistryImpl.java:157)
		at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
		at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841)
		at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
		at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2162)
		at org.neo4j.bolt.connection.routed.impl.cluster.RediscoveryImpl.lambda$lookupClusterComposition$0(RediscoveryImpl.java:115)
		at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
		at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841)
		at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
		at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2162)
		at org.neo4j.bolt.connection.routed.impl.cluster.RediscoveryImpl.lambda$lookupOnRouter$14(RediscoveryImpl.java:301)
		at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
		at java.base/java.util.concurrent.CompletableFuture.uniWhenCompleteStage(CompletableFuture.java:887)
		at java.base/java.util.concurrent.CompletableFuture.whenComplete(CompletableFuture.java:2325)
		at java.base/java.util.concurrent.CompletableFuture.whenComplete(CompletableFuture.java:144)
		at org.neo4j.bolt.connection.routed.impl.cluster.RediscoveryImpl.lambda$lookupOnRouter$16(RediscoveryImpl.java:292)
		at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
		at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841)
		at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
		at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2162)
		at org.neo4j.bolt.connection.routed.impl.cluster.RediscoveryImpl$1.onComplete(RediscoveryImpl.java:265)
		at org.neo4j.bolt.connection.pooled.impl.PooledBoltConnection$PooledResponseHandler.onComplete(PooledBoltConnection.java:259)
		at org.neo4j.bolt.connection.netty.impl.BoltConnectionImpl$ResponseHandleImpl.runIgnoringError(BoltConnectionImpl.java:748)
		at org.neo4j.bolt.connection.netty.impl.BoltConnectionImpl$ResponseHandleImpl.onComplete(BoltConnectionImpl.java:736)
		at org.neo4j.bolt.connection.netty.impl.BoltConnectionImpl$ResponseHandleImpl.lambda$new$0(BoltConnectionImpl.java:610)
		at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
		at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841)
		at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
		at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2147)
		at org.neo4j.bolt.connection.netty.impl.BoltConnectionImpl$ResponseHandleImpl.handleSummary(BoltConnectionImpl.java:742)
		at org.neo4j.bolt.connection.netty.impl.BoltConnectionImpl$ResponseHandleImpl.onError(BoltConnectionImpl.java:624)
		at org.neo4j.bolt.connection.netty.impl.BoltConnectionImpl$1.onError(BoltConnectionImpl.java:233)
		at org.neo4j.bolt.connection.netty.impl.messaging.v43.BoltProtocolV43.lambda$route$1(BoltProtocolV43.java:103)
		at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
		at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841)
		at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
		at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2162)
		at org.neo4j.bolt.connection.netty.impl.handlers.RouteMessageResponseHandler.onFailure(RouteMessageResponseHandler.java:52)
		at org.neo4j.bolt.connection.netty.impl.async.inbound.InboundMessageDispatcher.handleFailureMessage(InboundMessageDispatcher.java:108)
		at org.neo4j.bolt.connection.netty.impl.messaging.v57.MessageReaderV57.unpackFailureMessage(MessageReaderV57.java:46)
		at org.neo4j.bolt.connection.netty.impl.messaging.common.CommonMessageReader.read(CommonMessageReader.java:53)
		at org.neo4j.bolt.connection.netty.impl.async.inbound.InboundMessageHandler.channelRead0(InboundMessageHandler.java:81)
		at org.neo4j.bolt.connection.netty.impl.async.inbound.InboundMessageHandler.channelRead0(InboundMessageHandler.java:34)
		at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
		at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:361)
		at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:325)
		at org.neo4j.bolt.connection.netty.impl.async.inbound.MessageDecoder.channelRead(MessageDecoder.java:40)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
		at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:361)
		at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:325)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
		at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:289)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
		at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1357)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
		at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:868)
		at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
		at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:796)
		at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:732)
		at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:658)
		at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
		at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:998)
		at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
		at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
		at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: org.neo4j.driver.exceptions.Neo4jException: 22N51: A graph reference with the name `neo4j` was not found. Verify that the spelling is correct.
	at org.neo4j.driver.internal.adaptedbolt.ErrorMapper.mapGqlCause(ErrorMapper.java:179)
	at java.base/java.util.Optional.map(Optional.java:260)
	at org.neo4j.driver.internal.adaptedbolt.ErrorMapper.mapBoltFailureException(ErrorMapper.java:122)
	at org.neo4j.driver.internal.adaptedbolt.ErrorMapper.map(ErrorMapper.java:81)
	at org.neo4j.driver.internal.adaptedbolt.ErrorMapper.mapAndThrow(ErrorMapper.java:66)
	at java.base/java.util.concurrent.CompletableFuture.uniExceptionally(CompletableFuture.java:990)
	at java.base/java.util.concurrent.CompletableFuture$UniExceptionally.tryFire(CompletableFuture.java:974)
	at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
	at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2162)
	at org.neo4j.bolt.connection.routed.impl.cluster.RoutingTableRegistryImpl.lambda$ensureDatabaseNameIsCompleted$6(RoutingTableRegistryImpl.java:157)
	at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
	at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841)
	at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
	at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2162)
	at org.neo4j.bolt.connection.routed.impl.cluster.RediscoveryImpl.lambda$lookupClusterComposition$0(RediscoveryImpl.java:115)
	at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
	at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841)
	at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
	at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2162)
	at org.neo4j.bolt.connection.routed.impl.cluster.RediscoveryImpl.lambda$lookupOnRouter$14(RediscoveryImpl.java:301)
	at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
	at java.base/java.util.concurrent.CompletableFuture.uniWhenCompleteStage(CompletableFuture.java:887)
	at java.base/java.util.concurrent.CompletableFuture.whenComplete(CompletableFuture.java:2325)
	at java.base/java.util.concurrent.CompletableFuture.whenComplete(CompletableFuture.java:144)
	at org.neo4j.bolt.connection.routed.impl.cluster.RediscoveryImpl.lambda$lookupOnRouter$16(RediscoveryImpl.java:292)
	at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
	at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841)
	at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
	at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2162)
	at org.neo4j.bolt.connection.routed.impl.cluster.RediscoveryImpl$1.onComplete(RediscoveryImpl.java:265)
	at org.neo4j.bolt.connection.pooled.impl.PooledBoltConnection$PooledResponseHandler.onComplete(PooledBoltConnection.java:259)
	at org.neo4j.bolt.connection.netty.impl.BoltConnectionImpl$ResponseHandleImpl.runIgnoringError(BoltConnectionImpl.java:748)
	at org.neo4j.bolt.connection.netty.impl.BoltConnectionImpl$ResponseHandleImpl.onComplete(BoltConnectionImpl.java:736)
	at org.neo4j.bolt.connection.netty.impl.BoltConnectionImpl$ResponseHandleImpl.lambda$new$0(BoltConnectionImpl.java:610)
	at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
	at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841)
	at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
	at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2147)
	at org.neo4j.bolt.connection.netty.impl.BoltConnectionImpl$ResponseHandleImpl.handleSummary(BoltConnectionImpl.java:742)
	at org.neo4j.bolt.connection.netty.impl.BoltConnectionImpl$ResponseHandleImpl.onError(BoltConnectionImpl.java:624)
	at org.neo4j.bolt.connection.netty.impl.BoltConnectionImpl$1.onError(BoltConnectionImpl.java:233)
	at org.neo4j.bolt.connection.netty.impl.messaging.v43.BoltProtocolV43.lambda$route$1(BoltProtocolV43.java:103)
	at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
	at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841)
	at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
	at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2162)
	at org.neo4j.bolt.connection.netty.impl.handlers.RouteMessageResponseHandler.onFailure(RouteMessageResponseHandler.java:52)
	at org.neo4j.bolt.connection.netty.impl.async.inbound.InboundMessageDispatcher.handleFailureMessage(InboundMessageDispatcher.java:108)
	at org.neo4j.bolt.connection.netty.impl.messaging.v57.MessageReaderV57.unpackFailureMessage(MessageReaderV57.java:46)
	at org.neo4j.bolt.connection.netty.impl.messaging.common.CommonMessageReader.read(CommonMessageReader.java:53)
	at org.neo4j.bolt.connection.netty.impl.async.inbound.InboundMessageHandler.channelRead0(InboundMessageHandler.java:81)
	at org.neo4j.bolt.connection.netty.impl.async.inbound.InboundMessageHandler.channelRead0(InboundMessageHandler.java:34)
	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:361)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:325)
	at org.neo4j.bolt.connection.netty.impl.async.inbound.MessageDecoder.channelRead(MessageDecoder.java:40)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:361)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:325)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
	at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:289)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1357)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:868)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:796)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:732)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:658)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:998)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:833)

Configuration

spring:
  neo4j:
    uri: neo4j://127.0.0.1:7687
    authentication:
      username: neo4j
      password: xxxxxxx

  ai:
    openai:
      api-key: xxxxxxxxxxxxxxx
      base-url: https://dashscope.aliyuncs.com/compatible-mode

      chat:
        options:
          model: qwen-max-latest

      embedding:
        options:
          model: text-embedding-v4
          dimensions: 1024

    vectorstore:
      neo4j:
        initialize-schema: true
        database-name: my-db-name
        index-name: spring-ai-document-index
        embedding-dimension: 1024
        distance-type: cosine

Root Cause Analysis
I think the issue is in Neo4jVectorStore.doAdd() method. The code creates a session using this.driver.session() without passing the configured SessionConfig. My question is, why isn't sessionConfig used here? Instead, it using the default configuration. Is there a specific design consideration behind this?

public void doAdd(List<Document> documents) {
        List<float[]> embeddings = this.embeddingModel.embed(documents, EmbeddingOptions.builder().build(), this.batchingStrategy);
        List<Map<String, Object>> rows = documents.stream().map((document) -> {
            return this.documentToRecord(document, (float[])embeddings.get(documents.indexOf(document)));
        }).toList();

        // I think maybe issus is here
        Session session = this.driver.session();

        try {
            String statement = "\tUNWIND $rows AS row\n\tMERGE (u:%s {%2$s: row.id})\n\t\tSET u += row.properties\n\tWITH row, u\n\tCALL db.create.setNodeVectorProperty(u, $embeddingProperty, row[$embeddingProperty])\n".formatted(new Object[]{this.label, this.idProperty});
            session.executeWrite((tx) -> {
                return tx.run(statement, Map.of("rows", rows, "embeddingProperty", this.embeddingProperty)).consume();
            });
        } catch (Throwable var8) {
            if (session != null) {
                try {
                    session.close();
                } catch (Throwable var7) {
                    var8.addSuppressed(var7);
                }
            }

            throw var8;
        }

        if (session != null) {
            session.close();
        }

    }

Environment

  • Java Version: 17
  • Spring AI Version: 1.1.2

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions