Skip to content
VediramVediramSupport

Database queries are refused

databaseodbcpolicy

What you see

  • The AI agent says it cannot connect to a database, or that a connection was refused.
  • The agent says a query was "denied by policy" or "not allowed".
  • A table you know exists is missing from what the agent can see.
  • A query returns fewer rows than you expected.

Why it happens

The agent never connects to your databases directly. Levee gives it a list of approved data sources, named levee- followed by a short name (for example levee-sales). Each query the agent sends is checked against your organization's database rules on your computer, then run with your own database access.

So a query can fail for three kinds of reason:

  • The rules don't allow it: the data source, the table, or the kind of change (for example, deleting rows) is not permitted.
  • Your own database account can't do it. If it fails for you outside Levee, it fails inside too.
  • The project was stopping or restarting at that moment.

What you can try

  1. Look at the reason. Open the project in the Levee app and select the Activity tab. Database queries and refusals are listed there, with the reason.
  2. Restart the project. If the agent says it "failed to connect", stop the project and start it again, then ask the agent to retry.
  3. Ask for a smaller result. If you got fewer rows than expected, there is a limit on rows per query (10,000 by default). Ask the agent to filter the data, for example by date, or to fetch it in parts.
  4. Check your own access. If the database refuses the query even though Levee allowed it, check that you can run the same query yourself in your usual tool. If you can't, ask your database owner for access.
  5. Ask for the rule to change. If a data source, table or kind of query is not allowed and you need it, send your IT team the message from the Activity tab.

A table the rules don't allow is hidden, not just locked. The agent cannot see that it exists. That is expected.

For your IT team

Inside the sandbox, the agent sees an ordinary 64-bit ODBC driver named LeveeODBC and data sources named levee-<alias>. It never sees the real connection string, the credential, or any data source it was not granted. Each query is checked against the database access policy on the host, then run on the host through the user's own ODBC data source under the user's own database identity. See Database access.

Every connection, query and refusal is audited (odbc.connect, odbc.query, odbc.query.denied and related events). Audit records include the SQL text, truncated to 500 characters.

levee audit tail --lines 100
levee log tail --component proxy.odbc --project <project-id> --since 1h

The diagnostic log never contains SQL text or connection strings. The audit trail does include the SQL text and the reason.

Connection errors

SQLSTATE IM001: use SQLDriverConnect

The message reads "Use SQLDriverConnect with Driver=...;Alias=...". The tool called SQLConnect (the DSN / user / password form). LeveeODBC supports only SQLDriverConnect with one of these connection strings:

DSN=levee-<alias>
Driver={LeveeODBC};Alias=<alias>

Do not pass a user name or password: credentials stay on the host. Most libraries use SQLDriverConnect when given a full connection string. For example, in Python:

import pyodbc
conn = pyodbc.connect("DSN=levee-sales")

SQLSTATE HY000: connection string must contain an alias

The message reads "Connection string must contain 'Alias=...' or 'DSN=levee-...'". The connection string names neither an alias nor a levee- data source. Use one of the forms above.

SQLSTATE 08004: "Connection refused: unknown or unauthorized alias"

The alias has no rule in policy, or its rule is invalid. Alias names use letters, digits, - and _ only (up to 64 characters). Add a rule for the data source. See Database access.

SQLSTATE 08004: "Connection refused: audit unavailable (fail closed)"

Levee could not record the connection in the audit trail, so it refused the connection. Restart the project. If it persists, check the Levee service with levee doctor.

SQLSTATE 08001: "Failed to connect"

The driver could not reach Levee on the host, usually because the project is stopping or restarting. Restart the project.

The host data source fails

If the policy is fine but the query fails with "Query execution failed. See host logs for details.", the host side could not run it. Check that the hostDsn in policy exists on the host as a 64-bit ODBC data source for the signed-in user and works outside Levee:

Get-OdbcDsn -Platform '64-bit' | Select-Object Name, DsnType, DriverName

32-bit data sources are not visible to Levee. Database permissions come from the user's own login on the host.

Query refusals (SQLSTATE 42000)

MessageCauseFix
No policy configured; query denied (fail closed)No database policy reached the project yet.Sync policy, then restart the project.
No policy rule for alias '<alias>' and default is denyThe alias has no rule.Add a rule for the alias.
Verb <VERB> is explicitly deniedThe statement type is in the rule's deniedVerbs.Expected. Change policy if the verb should be allowed.
Verb <VERB> is not in allowed verbs [...]The statement type is not in allowedVerbs.Add the verb to allowedVerbs if appropriate.
Table '<t>' is denied by policy / Table '<t>' is not allowed by policyThe query touches a table outside the rule's table allow list, or in its deny list.Adjust tables.allow / tables.deny. Deny always wins over allow.
Multiple SQL statements in a single request are not allowedThe request contains more than one statement.Send one statement per call.
Dangerous SQL pattern blocked: <pattern>The query contains a blocked construct such as xp_cmdshell, OPENROWSET, OPENDATASOURCE, xp_regread, sp_oacreate or BULK INSERT.These are always blocked.
Unrecognized SQL statement denied (verb could not be classified)Levee could not tell what kind of statement this is (for example, a statement starting with (, DECLARE, USE or WAITFOR). Unrecognized statements are denied, never passed through.Rewrite as a plain SELECT, INSERT, UPDATE, etc.

Statement types Levee recognizes: SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, TRUNCATE, EXEC / EXECUTE, MERGE, GRANT, REVOKE, DENY. A statement that starts with a WITH common table expression is classified by the statement that follows it.

Other errors

SQLSTATEMessageFix
HYT00Query timed out and was terminated by policy.The query ran longer than the rule's queryTimeoutSeconds (30 by default). Optimize the query or raise the limit.
HY000Query refused: audit channel unavailable (fail closed)Levee could not audit the query. Restart the project.
HY000Query execution failed. See host logs for details.The database rejected the query. See "The host data source fails" above.
08003Invalid or expired connection IDThe connection was closed (for example, the project restarted). Reconnect.

A table is missing from the table list

Metadata calls (SQLTables, SQLColumns) are filtered by the same policy as queries. Tables the rule does not allow are not shown at all. If a table should be visible, add it to the rule's tables.allow.

Fewer rows than expected

Each rule has a row cap, maxRowsPerQuery (10,000 by default). Rows beyond the cap are not returned, and the host log records a truncation warning. Add a WHERE clause or paging, or raise the cap.

Driver limitations

LeveeODBC supports direct execution (SQLExecDirect) of single statements. Tools that depend on these ODBC features will not work through it:

  • Prepared statements and bound parameters (SQLPrepare, SQLExecute, SQLBindParameter)
  • Bound result columns (SQLBindCol); use SQLGetData
  • SQLPrimaryKeys, SQLStatistics, SQLGetTypeInfo
  • Affected-row counts: SQLRowCount returns -1
  • Explicit transactions: SQLEndTran has no effect; the host data source's default transaction behavior applies

DECIMAL and NUMERIC values are returned as floating-point numbers, so very high-precision values can lose precision.

Before you open a request

Send the odbc.* audit events and the proxy.odbc log. See Collecting logs for support.