Parameter 0 of function 'array_contains()' requires an array type, but argument is of type 'java.lang.String[]'

Tested with latest 6.6.0-SNAPSHOT:

org.hibernate.query.sqm.produce.function.FunctionArgumentException: Parameter 0 of function 'array_contains()' requires an array type, but argument is of type 'java.lang.String[]'
	at org.hibernate.dialect.function.array.ArrayArgumentValidator.getPluralType(ArrayArgumentValidator.java:64)
	at org.hibernate.dialect.function.array.ArrayContainsArgumentValidator.validate(ArrayContainsArgumentValidator.java:35)
	at org.hibernate.query.sqm.produce.function.StandardArgumentsValidators$8.lambda$validate$0(StandardArgumentsValidators.java:254)
	at java.base/java.util.Arrays$ArrayList.forEach(Arrays.java:4204)
	at org.hibernate.query.sqm.produce.function.StandardArgumentsValidators$8.validate(StandardArgumentsValidators.java:254)
	at org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor.generateSqmExpression(AbstractSqmFunctionDescriptor.java:102)
	at org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder.function(SqmCriteriaNodeBuilder.java:1732)
	at org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder.function(SqmCriteriaNodeBuilder.java:190)
	at com.example.demo.PostgreSQLTests.test(PostgreSQLTests.java:87)
	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)

Here is the test case:

package com.example.demo;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.LinkedHashSet;
import java.util.Set;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testcontainers.service.connection.ServiceConnectionAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.test.context.TestPropertySource;
import org.testcontainers.containers.PostgreSQLContainer;

import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Convert;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityManager;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;

@DataJpaTest
@EntityScan(basePackageClasses = PostgreSQLArrayTests.class)
@EnableJpaRepositories(considerNestedRepositories = true)
@AutoConfigureTestDatabase(replace = Replace.NONE)
@TestPropertySource(properties = { "spring.jpa.hibernate.ddl-auto=update",
		"logging.level.org.hibernate.orm.jdbc.bind=TRACE" })
public class PostgreSQLArrayTests {

	@Autowired
	EntityManager entityManager;

	@Test
	void arrayContains() {
		TestEntity entity = new TestEntity();
		entity.tags = Set.of("foo", "bar");
		entityManager.persist(entity);
		entityManager.flush();
		entityManager.clear();

		TestEntity persisted = entityManager.find(TestEntity.class, entity.id);
		assertThat(persisted.tags).isEqualTo(entity.tags);

		CriteriaBuilder cb = entityManager.getCriteriaBuilder();
		CriteriaQuery<TestEntity> cq = cb.createQuery(TestEntity.class);
		Root<TestEntity> root = cq.from(TestEntity.class);
		cq.where(cb.isTrue(cb.function("array_contains", Boolean.class,
				cb.function("string_to_array", String[].class, root.get("tags"), cb.literal(",")), cb.literal("foo"))));
		assertThat(entityManager.createQuery(cq).getResultList()).hasSize(1);
	}

	public static interface TestEntityRepository
			extends JpaRepository<TestEntity, Long>, JpaSpecificationExecutor<TestEntity> {

	}

	@Configuration
	@ImportAutoConfiguration(classes = ServiceConnectionAutoConfiguration.class)
	static class Config {

		@Bean
		@ServiceConnection
		PostgreSQLContainer<?> container() {
			return new PostgreSQLContainer<>("postgres");
		}
	}

	@Entity
	public static class TestEntity {

		@Id
		@GeneratedValue
		Long id;

		@Convert(converter = SetConverter.class)
		Set<String> tags;

	}

	static class SetConverter implements AttributeConverter<Set<String>, String> {

		@Override
		public String convertToDatabaseColumn(Set<String> attribute) {
			if (attribute == null)
				return null;
			return String.join(",", attribute);
		}

		@Override
		public Set<String> convertToEntityAttribute(String dbData) {
			if (dbData == null)
				return null;
			Set<String> result = new LinkedHashSet<>();
			result.addAll(Set.of(dbData.split(",")));
			return result;
		}

	}
}
		TypedQuery<TestEntity> query = entityManager.createQuery(
				"from TestEntity where array_contains(string_to_array(tags, ','), 'foo')", TestEntity.class);
		assertThat(query.getResultList()).hasSize(1);

will produce error:

Caused by: org.hibernate.query.sqm.produce.function.FunctionArgumentException: Parameter 0 of function 'array_contains()' requires an array type, but argument is of type 'java.lang.Object'
	at org.hibernate.dialect.function.array.ArrayArgumentValidator.getPluralType(ArrayArgumentValidator.java:64)
	at org.hibernate.dialect.function.array.ArrayContainsArgumentValidator.validate(ArrayContainsArgumentValidator.java:35)
	at org.hibernate.query.sqm.produce.function.StandardArgumentsValidators$8.lambda$validate$0(StandardArgumentsValidators.java:254)
	at java.base/java.util.Arrays$ArrayList.forEach(Arrays.java:4204)
	at org.hibernate.query.sqm.produce.function.StandardArgumentsValidators$8.validate(StandardArgumentsValidators.java:254)
	at org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor.generateSqmExpression(AbstractSqmFunctionDescriptor.java:102)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitGenericFunction(SemanticQueryBuilder.java:4075)
	at org.hibernate.grammars.hql.HqlParser$GenericFunctionContext.accept(HqlParser.java:12429)
	at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visitChildren(AbstractParseTreeVisitor.java:46)
	at org.hibernate.grammars.hql.HqlParserBaseVisitor.visitFunction(HqlParserBaseVisitor.java:1302)
	at org.hibernate.grammars.hql.HqlParser$FunctionContext.accept(HqlParser.java:11907)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitFunctionExpression(SemanticQueryBuilder.java:1897)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitFunctionExpression(SemanticQueryBuilder.java:275)
	at org.hibernate.grammars.hql.HqlParser$FunctionExpressionContext.accept(HqlParser.java:7891)
	at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visitChildren(AbstractParseTreeVisitor.java:46)
	at org.hibernate.grammars.hql.HqlParserBaseVisitor.visitBarePrimaryExpression(HqlParserBaseVisitor.java:777)
	at org.hibernate.grammars.hql.HqlParser$BarePrimaryExpressionContext.accept(HqlParser.java:7469)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitBooleanExpressionPredicate(SemanticQueryBuilder.java:2830)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitBooleanExpressionPredicate(SemanticQueryBuilder.java:275)
	at org.hibernate.grammars.hql.HqlParser$BooleanExpressionPredicateContext.accept(HqlParser.java:6543)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitWhereClause(SemanticQueryBuilder.java:2356)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitWhereClause(SemanticQueryBuilder.java:275)
	at org.hibernate.grammars.hql.HqlParser$WhereClauseContext.accept(HqlParser.java:6217)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitQuery(SemanticQueryBuilder.java:1254)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitQuerySpecExpression(SemanticQueryBuilder.java:1035)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitQuerySpecExpression(SemanticQueryBuilder.java:275)
	at org.hibernate.grammars.hql.HqlParser$QuerySpecExpressionContext.accept(HqlParser.java:2132)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSimpleQueryGroup(SemanticQueryBuilder.java:1020)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSimpleQueryGroup(SemanticQueryBuilder.java:275)
	at org.hibernate.grammars.hql.HqlParser$SimpleQueryGroupContext.accept(HqlParser.java:2003)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSelectStatement(SemanticQueryBuilder.java:490)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitStatement(SemanticQueryBuilder.java:449)
	at org.hibernate.query.hql.internal.SemanticQueryBuilder.buildSemanticModel(SemanticQueryBuilder.java:322)
	at org.hibernate.query.hql.internal.StandardHqlTranslator.translate(StandardHqlTranslator.java:71)
	at org.hibernate.query.internal.QueryInterpretationCacheStandardImpl.createHqlInterpretation(QueryInterpretationCacheStandardImpl.java:145)
	at org.hibernate.query.internal.QueryInterpretationCacheStandardImpl.resolveHqlInterpretation(QueryInterpretationCacheStandardImpl.java:132)
	at org.hibernate.internal.AbstractSharedSessionContract.interpretHql(AbstractSharedSessionContract.java:830)
	at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:880)
	... 11 more

What is this string_to_array function?

PostgreSQL native function.

The string_to_array() function is not registered in the PostgreSQLDialect, so my guess is that you did not register the function correctly. The return type of that function must be a plural type i.e. through DdlTypeHelper.resolveArrayType( typeConfiguration.getBasicTypeForJavaType(String.class), typeConfiguration )