When using the local Temporal(version 1.21.4) development server I can’t query search attributes containing a slash(/). This will throw an SQL logic error.
I have added some example code that makes it easy to reproduce, just run temporal server start-dev
and it should fail immediately.
package main
import (
"context"
"fmt"
"go.temporal.io/api/enums/v1"
"go.temporal.io/api/operatorservice/v1"
"go.temporal.io/api/serviceerror"
"go.temporal.io/api/workflowservice/v1"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/workflow"
)
func main() {
temporalClient, err := client.Dial(client.Options{
HostPort: "localhost:7233",
Namespace: "default",
})
if err != nil {
panic(err)
}
_, err = temporalClient.OperatorService().AddSearchAttributes(context.Background(), &operatorservice.AddSearchAttributesRequest{
SearchAttributes: map[string]enums.IndexedValueType{
"Workspace": enums.INDEXED_VALUE_TYPE_TEXT,
},
Namespace: "default",
})
if err != nil {
if _, ok := err.(*serviceerror.AlreadyExists); !ok {
panic(err)
}
}
fmt.Println("This one will execute just fine")
list(temporalClient)
temporalClient.ExecuteWorkflow(context.Background(), client.StartWorkflowOptions{TaskQueue: "default"}, TestWorkflow)
fmt.Println("This one will fail")
list(temporalClient)
}
func list(c client.Client) {
_, err := c.ListWorkflow(context.Background(), &workflowservice.ListWorkflowExecutionsRequest{
Namespace: "default",
Query: "Workspace = 'terraform/gcp/cluster/cluster-1'",
})
if err != nil {
panic(err)
}
}
func TestWorkflow(ctx workflow.Context) error {
return nil
}
{
"level": "error",
"ts": "2023-09-01T14:42:34.528+0200",
"msg": "service failures",
"operation": "ListWorkflowExecutions",
"wf-namespace": "A NAMESPACE IS HERE",
"error": "ListWorkflowExecutions operation failed. Select failed: SQL logic error: fts5: syntax error near \"/\" (1)",
"logging-call-at": "telemetry.go:330",
"stacktrace": "go.temporal.io/server/common/log.(*zapLogger).Error\n\tgo.temporal.io/server@v1.21.4/common/log/zap_logger.go:156\ngo.temporal.io/server/common/rpc/interceptor.(*TelemetryInterceptor).handleError\n\tgo.temporal.io/server@v1.21.4/common/rpc/interceptor/telemetry.go:330\ngo.temporal.io/server/common/rpc/interceptor.(*TelemetryInterceptor).UnaryIntercept\n\tgo.temporal.io/server@v1.21.4/common/rpc/interceptor/telemetry.go:171\ngoogle.golang.org/grpc.getChainUnaryHandler.func1\n\tgoogle.golang.org/grpc@v1.57.0/server.go:1179\ngo.temporal.io/server/service/frontend.(*RedirectionInterceptor).handleRedirectAPIInvocation.func2\n\tgo.temporal.io/server@v1.21.4/service/frontend/redirection_interceptor.go:238\ngo.temporal.io/server/service/frontend.(*NoopRedirectionPolicy).WithNamespaceRedirect\n\tgo.temporal.io/server@v1.21.4/service/frontend/dcRedirectionPolicy.go:125\ngo.temporal.io/server/service/frontend.(*RedirectionInterceptor).handleRedirectAPIInvocation\n\tgo.temporal.io/server@v1.21.4/service/frontend/redirection_interceptor.go:235\ngo.temporal.io/server/service/frontend.(*RedirectionInterceptor).Intercept\n\tgo.temporal.io/server@v1.21.4/service/frontend/redirection_interceptor.go:195\ngoogle.golang.org/grpc.getChainUnaryHandler.func1\n\tgoogle.golang.org/grpc@v1.57.0/server.go:1179\ngo.temporal.io/server/common/metrics.NewServerMetricsContextInjectorInterceptor.func1\n\tgo.temporal.io/server@v1.21.4/common/metrics/grpc.go:66\ngoogle.golang.org/grpc.getChainUnaryHandler.func1\n\tgoogle.golang.org/grpc@v1.57.0/server.go:1179\ngo.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc.UnaryServerInterceptor.func1\n\tgo.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc@v0.42.0/interceptor.go:344\ngoogle.golang.org/grpc.getChainUnaryHandler.func1\n\tgoogle.golang.org/grpc@v1.57.0/server.go:1179\ngo.temporal.io/server/common/rpc/interceptor.(*NamespaceLogInterceptor).Intercept\n\tgo.temporal.io/server@v1.21.4/common/rpc/interceptor/namespace_logger.go:84\ngoogle.golang.org/grpc.getChainUnaryHandler.func1\n\tgoogle.golang.org/grpc@v1.57.0/server.go:1179\ngo.temporal.io/server/common/rpc/interceptor.(*NamespaceValidatorInterceptor).NamespaceValidateIntercept\n\tgo.temporal.io/server@v1.21.4/common/rpc/interceptor/namespace_validator.go:111\ngoogle.golang.org/grpc.getChainUnaryHandler.func1\n\tgoogle.golang.org/grpc@v1.57.0/server.go:1179\ngo.temporal.io/server/common/rpc.ServiceErrorInterceptor\n\tgo.temporal.io/server@v1.21.4/common/rpc/grpc.go:141\ngoogle.golang.org/grpc.chainUnaryInterceptors.func1\n\tgoogle.golang.org/grpc@v1.57.0/server.go:1170\ngo.temporal.io/api/workflowservice/v1._WorkflowService_ListWorkflowExecutions_Handler\n\tgo.temporal.io/api@v1.23.0/workflowservice/v1/service.pb.go:1965\ngoogle.golang.org/grpc.(*Server).processUnaryRPC\n\tgoogle.golang.org/grpc@v1.57.0/server.go:1360\ngoogle.golang.org/grpc.(*Server).handleStream\n\tgoogle.golang.org/grpc@v1.57.0/server.go:1737\ngoogle.golang.org/grpc.(*Server).serveStreams.func1.1\n\tgoogle.golang.org/grpc@v1.57.0/server.go:982"
}