This is an automated email from the ASF dual-hosted git repository.
rusackas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new b7a5b24a54 feat(docs): add auto-generated troubleshooting section to
database pages (#37345)
b7a5b24a54 is described below
commit b7a5b24a54150695db9933a7f9ea4a7916b5468b
Author: Evan Rusackas <[email protected]>
AuthorDate: Thu Jan 22 14:43:02 2026 -0800
feat(docs): add auto-generated troubleshooting section to database pages
(#37345)
Co-authored-by: Claude Opus 4.5 <[email protected]>
---
docs/scripts/extract_custom_errors.py | 296 ++++++++
docs/scripts/generate-database-docs.mjs | 76 ++
docs/src/components/databases/DatabaseIndex.tsx | 16 +-
docs/src/components/databases/DatabasePage.tsx | 130 ++++
docs/src/components/databases/types.ts | 12 +
docs/src/data/databases.json | 953 +++++++++++++++++++++++-
6 files changed, 1473 insertions(+), 10 deletions(-)
diff --git a/docs/scripts/extract_custom_errors.py
b/docs/scripts/extract_custom_errors.py
new file mode 100644
index 0000000000..35aee1cdbc
--- /dev/null
+++ b/docs/scripts/extract_custom_errors.py
@@ -0,0 +1,296 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+Extract custom_errors from database engine specs for documentation.
+
+This script parses engine spec files to extract error handling information
+that can be displayed on database documentation pages.
+
+Usage: python scripts/extract_custom_errors.py
+Output: JSON mapping of engine spec module names to their custom errors
+"""
+
+import ast
+import json # noqa: TID251 - standalone docs script, not part of superset
+import sys
+from pathlib import Path
+from typing import Any
+
+# Map SupersetErrorType values to human-readable categories and issue codes
+ERROR_TYPE_INFO = {
+ "CONNECTION_INVALID_USERNAME_ERROR": {
+ "category": "Authentication",
+ "description": "Invalid username",
+ "issue_codes": [1012],
+ },
+ "CONNECTION_INVALID_PASSWORD_ERROR": {
+ "category": "Authentication",
+ "description": "Invalid password",
+ "issue_codes": [1013],
+ },
+ "CONNECTION_ACCESS_DENIED_ERROR": {
+ "category": "Authentication",
+ "description": "Access denied",
+ "issue_codes": [1014, 1015],
+ },
+ "CONNECTION_INVALID_HOSTNAME_ERROR": {
+ "category": "Connection",
+ "description": "Invalid hostname",
+ "issue_codes": [1007],
+ },
+ "CONNECTION_PORT_CLOSED_ERROR": {
+ "category": "Connection",
+ "description": "Port closed or refused",
+ "issue_codes": [1008],
+ },
+ "CONNECTION_HOST_DOWN_ERROR": {
+ "category": "Connection",
+ "description": "Host unreachable",
+ "issue_codes": [1009],
+ },
+ "CONNECTION_UNKNOWN_DATABASE_ERROR": {
+ "category": "Connection",
+ "description": "Unknown database",
+ "issue_codes": [1015],
+ },
+ "CONNECTION_DATABASE_PERMISSIONS_ERROR": {
+ "category": "Permissions",
+ "description": "Insufficient permissions",
+ "issue_codes": [1017],
+ },
+ "CONNECTION_MISSING_PARAMETERS_ERROR": {
+ "category": "Configuration",
+ "description": "Missing parameters",
+ "issue_codes": [1018],
+ },
+ "CONNECTION_DATABASE_TIMEOUT": {
+ "category": "Connection",
+ "description": "Connection timeout",
+ "issue_codes": [1001, 1009],
+ },
+ "COLUMN_DOES_NOT_EXIST_ERROR": {
+ "category": "Query",
+ "description": "Column not found",
+ "issue_codes": [1003, 1004],
+ },
+ "TABLE_DOES_NOT_EXIST_ERROR": {
+ "category": "Query",
+ "description": "Table not found",
+ "issue_codes": [1003, 1005],
+ },
+ "SCHEMA_DOES_NOT_EXIST_ERROR": {
+ "category": "Query",
+ "description": "Schema not found",
+ "issue_codes": [1003, 1016],
+ },
+ "SYNTAX_ERROR": {
+ "category": "Query",
+ "description": "SQL syntax error",
+ "issue_codes": [1030],
+ },
+ "OBJECT_DOES_NOT_EXIST_ERROR": {
+ "category": "Query",
+ "description": "Object not found",
+ "issue_codes": [1029],
+ },
+ "GENERIC_DB_ENGINE_ERROR": {
+ "category": "General",
+ "description": "Database engine error",
+ "issue_codes": [1002],
+ },
+}
+
+
+def extract_string_from_call(node: ast.Call) -> str | None:
+ """Extract string from __() or _() translation calls."""
+ if not node.args:
+ return None
+ arg = node.args[0]
+ if isinstance(arg, ast.Constant) and isinstance(arg.value, str):
+ return arg.value
+ elif isinstance(arg, ast.JoinedStr):
+ # f-string - try to reconstruct
+ parts = []
+ for value in arg.values:
+ if isinstance(value, ast.Constant):
+ parts.append(str(value.value))
+ elif isinstance(value, ast.FormattedValue):
+ # Just use a placeholder
+ parts.append("{...}")
+ return "".join(parts)
+ return None
+
+
+def extract_custom_errors_from_file(filepath: Path) -> dict[str,
list[dict[str, Any]]]:
+ """
+ Extract custom_errors definitions from a Python engine spec file.
+
+ Returns a dict mapping class names to their custom errors list.
+ """
+ results = {}
+
+ try:
+ with open(filepath, "r", encoding="utf-8") as f:
+ source = f.read()
+
+ tree = ast.parse(source)
+
+ for node in ast.walk(tree):
+ if isinstance(node, ast.ClassDef):
+ class_name = node.name
+
+ for item in node.body:
+ # Look for custom_errors = { ... }
+ if (
+ isinstance(item, ast.AnnAssign)
+ and isinstance(item.target, ast.Name)
+ and item.target.id == "custom_errors"
+ and isinstance(item.value, ast.Dict)
+ ):
+ errors = extract_errors_from_dict(item.value, source)
+ if errors:
+ results[class_name] = errors
+
+ # Also handle simple assignment: custom_errors = { ... }
+ elif (
+ isinstance(item, ast.Assign)
+ and len(item.targets) == 1
+ and isinstance(item.targets[0], ast.Name)
+ and item.targets[0].id == "custom_errors"
+ and isinstance(item.value, ast.Dict)
+ ):
+ errors = extract_errors_from_dict(item.value, source)
+ if errors:
+ results[class_name] = errors
+
+ except (OSError, SyntaxError, ValueError) as e:
+ print(f"Error parsing {filepath}: {e}", file=sys.stderr)
+
+ return results
+
+
+def extract_regex_info(key: ast.expr) -> dict[str, Any]:
+ """Extract regex pattern info from the dict key."""
+ if isinstance(key, ast.Name):
+ return {"regex_name": key.id}
+ if isinstance(key, ast.Call):
+ if (
+ isinstance(key.func, ast.Attribute)
+ and key.func.attr == "compile"
+ and key.args
+ and isinstance(key.args[0], ast.Constant)
+ ):
+ return {"regex_pattern": key.args[0].value}
+ return {}
+
+
+def extract_invalid_fields(extra_node: ast.Dict) -> list[str]:
+ """Extract invalid fields from the extra dict."""
+ for k, v in zip(extra_node.keys, extra_node.values, strict=False):
+ if (
+ isinstance(k, ast.Constant)
+ and k.value == "invalid"
+ and isinstance(v, ast.List)
+ ):
+ return [elem.value for elem in v.elts if isinstance(elem,
ast.Constant)]
+ return []
+
+
+def extract_error_tuple_info(value: ast.Tuple) -> dict[str, Any]:
+ """Extract error info from the (message, error_type, extra) tuple."""
+ result: dict[str, Any] = {}
+
+ # First element: message template
+ msg_node = value.elts[0]
+ if isinstance(msg_node, ast.Call):
+ message = extract_string_from_call(msg_node)
+ if message:
+ result["message_template"] = message
+ elif isinstance(msg_node, ast.Constant):
+ result["message_template"] = msg_node.value
+
+ # Second element: SupersetErrorType.SOMETHING
+ type_node = value.elts[1]
+ if isinstance(type_node, ast.Attribute):
+ error_type = type_node.attr
+ result["error_type"] = error_type
+ if error_type in ERROR_TYPE_INFO:
+ type_info = ERROR_TYPE_INFO[error_type]
+ result["category"] = type_info["category"]
+ result["description"] = type_info["description"]
+ result["issue_codes"] = type_info["issue_codes"]
+
+ # Third element: extra dict with invalid fields
+ if len(value.elts) >= 3 and isinstance(value.elts[2], ast.Dict):
+ invalid_fields = extract_invalid_fields(value.elts[2])
+ if invalid_fields:
+ result["invalid_fields"] = invalid_fields
+
+ return result
+
+
+def extract_errors_from_dict(dict_node: ast.Dict, source: str) ->
list[dict[str, Any]]:
+ """Extract error information from a custom_errors dict AST node."""
+ errors = []
+
+ for key, value in zip(dict_node.keys, dict_node.values, strict=False):
+ if key is None or value is None:
+ continue
+
+ error_info = extract_regex_info(key)
+
+ if isinstance(value, ast.Tuple) and len(value.elts) >= 2:
+ error_info.update(extract_error_tuple_info(value))
+
+ if error_info.get("error_type") and error_info.get("message_template"):
+ errors.append(error_info)
+
+ return errors
+
+
+def main() -> None:
+ """Main function to extract custom_errors from all engine specs."""
+ # Find the superset root directory
+ script_dir = Path(__file__).parent
+ root_dir = script_dir.parent.parent
+ specs_dir = root_dir / "superset" / "db_engine_specs"
+
+ if not specs_dir.exists():
+ print(f"Error: Engine specs directory not found: {specs_dir}",
file=sys.stderr)
+ sys.exit(1)
+
+ all_errors = {}
+
+ # Process each Python file in the specs directory
+ for filepath in sorted(specs_dir.glob("*.py")):
+ if filepath.name.startswith("_"):
+ continue
+
+ module_name = filepath.stem
+ class_errors = extract_custom_errors_from_file(filepath)
+
+ if class_errors:
+ # Store errors by module and class
+ all_errors[module_name] = class_errors
+
+ # Output as JSON
+ print(json.dumps(all_errors, indent=2))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/docs/scripts/generate-database-docs.mjs
b/docs/scripts/generate-database-docs.mjs
index cde02d127d..04980f24f8 100644
--- a/docs/scripts/generate-database-docs.mjs
+++ b/docs/scripts/generate-database-docs.mjs
@@ -675,6 +675,78 @@ function updateReadme(databases) {
return false;
}
+/**
+ * Extract custom_errors from engine specs for troubleshooting documentation
+ * Returns a map of module names to their custom errors
+ */
+function extractCustomErrors() {
+ console.log('Extracting custom_errors from engine specs...');
+
+ try {
+ const scriptPath = path.join(__dirname, 'extract_custom_errors.py');
+ const result = spawnSync('python3', [scriptPath], {
+ cwd: ROOT_DIR,
+ encoding: 'utf-8',
+ timeout: 30000,
+ maxBuffer: 10 * 1024 * 1024,
+ });
+
+ if (result.error) {
+ throw result.error;
+ }
+ if (result.status !== 0) {
+ throw new Error(result.stderr || 'Python script failed');
+ }
+
+ const customErrors = JSON.parse(result.stdout);
+ const moduleCount = Object.keys(customErrors).length;
+ const errorCount = Object.values(customErrors).reduce((sum, classes) =>
+ sum + Object.values(classes).reduce((s, errs) => s + errs.length, 0), 0);
+ console.log(` Found ${errorCount} custom errors across ${moduleCount}
modules`);
+ return customErrors;
+ } catch (err) {
+ console.log(' Could not extract custom_errors:', err.message);
+ return null;
+ }
+}
+
+/**
+ * Merge custom_errors into database documentation
+ * Maps by module name since that's how both datasets are keyed
+ */
+function mergeCustomErrors(databases, customErrors) {
+ if (!customErrors) return;
+
+ let mergedCount = 0;
+
+ for (const [, db] of Object.entries(databases)) {
+ if (!db.module) continue;
+ // Normalize module name: Flask mode uses full path
(superset.db_engine_specs.postgres),
+ // but customErrors is keyed by file stem (postgres)
+ const moduleName = db.module.split('.').pop();
+ if (!customErrors[moduleName]) continue;
+
+ // Get all errors from all classes in this module
+ const moduleErrors = customErrors[moduleName];
+ const allErrors = [];
+
+ for (const classErrors of Object.values(moduleErrors)) {
+ allErrors.push(...classErrors);
+ }
+
+ if (allErrors.length > 0) {
+ // Add to documentation
+ db.documentation = db.documentation || {};
+ db.documentation.custom_errors = allErrors;
+ mergedCount++;
+ }
+ }
+
+ if (mergedCount > 0) {
+ console.log(` Merged custom_errors into ${mergedCount} database docs`);
+ }
+}
+
/**
* Load existing database data if available
*/
@@ -768,6 +840,10 @@ async function main() {
databases = mergeWithExistingDiagnostics(databases, existingData);
}
+ // Extract and merge custom_errors for troubleshooting documentation
+ const customErrors = extractCustomErrors();
+ mergeCustomErrors(databases, customErrors);
+
// Build statistics
const statistics = buildStatistics(databases);
diff --git a/docs/src/components/databases/DatabaseIndex.tsx
b/docs/src/components/databases/DatabaseIndex.tsx
index 89eee4782d..fee4f1a36b 100644
--- a/docs/src/components/databases/DatabaseIndex.tsx
+++ b/docs/src/components/databases/DatabaseIndex.tsx
@@ -26,6 +26,7 @@ import {
KeyOutlined,
SearchOutlined,
LinkOutlined,
+ BugOutlined,
} from '@ant-design/icons';
import type { DatabaseData, DatabaseInfo, TimeGrains } from './types';
@@ -44,6 +45,8 @@ interface TableEntry {
hasDrivers: boolean;
hasAuthMethods: boolean;
hasConnectionString: boolean;
+ hasCustomErrors: boolean;
+ customErrorCount: number;
joins?: boolean;
subqueries?: boolean;
supports_dynamic_schema?: boolean;
@@ -223,6 +226,8 @@ const DatabaseIndex: React.FC<DatabaseIndexProps> = ({ data
}) => {
db.documentation?.connection_string ||
(db.documentation?.drivers?.length ?? 0) > 0
),
+ hasCustomErrors: (db.documentation?.custom_errors?.length ?? 0) > 0,
+ customErrorCount: db.documentation?.custom_errors?.length ?? 0,
isCompatible: false,
});
@@ -246,6 +251,8 @@ const DatabaseIndex: React.FC<DatabaseIndexProps> = ({ data
}) => {
hasDrivers: false,
hasAuthMethods: false,
hasConnectionString: Boolean(compat.connection_string),
+ hasCustomErrors: false,
+ customErrorCount: 0,
joins: db.joins,
subqueries: db.subqueries,
supports_dynamic_schema: db.supports_dynamic_schema,
@@ -457,7 +464,7 @@ const DatabaseIndex: React.FC<DatabaseIndexProps> = ({ data
}) => {
{
title: 'Documentation',
key: 'docs',
- width: 150,
+ width: 180,
render: (_: unknown, record: TableEntry) => (
<div style={{ display: 'flex', gap: '4px', flexWrap: 'wrap' }}>
{record.hasConnectionString && (
@@ -475,6 +482,13 @@ const DatabaseIndex: React.FC<DatabaseIndexProps> = ({
data }) => {
Auth
</Tag>
)}
+ {record.hasCustomErrors && (
+ <Tooltip title={`${record.customErrorCount} troubleshooting tips`}>
+ <Tag icon={<BugOutlined />} color="volcano">
+ Errors
+ </Tag>
+ </Tooltip>
+ )}
</div>
),
},
diff --git a/docs/src/components/databases/DatabasePage.tsx
b/docs/src/components/databases/DatabasePage.tsx
index 836680b746..c02d4a44a1 100644
--- a/docs/src/components/databases/DatabasePage.tsx
+++ b/docs/src/components/databases/DatabasePage.tsx
@@ -39,6 +39,7 @@ import {
BookOutlined,
EditOutlined,
GithubOutlined,
+ BugOutlined,
} from '@ant-design/icons';
import type { DatabaseInfo } from './types';
@@ -414,6 +415,132 @@ const DatabasePage: React.FC<DatabasePageProps> = ({
database, name }) => {
);
};
+ // Render troubleshooting / custom errors section
+ const renderTroubleshooting = () => {
+ if (!docs?.custom_errors?.length) return null;
+
+ // Group errors by category
+ const errorsByCategory: Record<string, typeof docs.custom_errors> = {};
+ for (const error of docs.custom_errors) {
+ const category = error.category || 'General';
+ if (!errorsByCategory[category]) {
+ errorsByCategory[category] = [];
+ }
+ errorsByCategory[category].push(error);
+ }
+
+ // Define category order for consistent display
+ const categoryOrder = [
+ 'Authentication',
+ 'Connection',
+ 'Permissions',
+ 'Query',
+ 'Configuration',
+ 'General',
+ ];
+
+ const sortedCategories = Object.keys(errorsByCategory).sort((a, b) => {
+ const aIdx = categoryOrder.indexOf(a);
+ const bIdx = categoryOrder.indexOf(b);
+ if (aIdx === -1 && bIdx === -1) return a.localeCompare(b);
+ if (aIdx === -1) return 1;
+ if (bIdx === -1) return -1;
+ return aIdx - bIdx;
+ });
+
+ // Category colors
+ const categoryColors: Record<string, string> = {
+ Authentication: 'orange',
+ Connection: 'red',
+ Permissions: 'purple',
+ Query: 'blue',
+ Configuration: 'cyan',
+ General: 'default',
+ };
+
+ return (
+ <Card
+ title={
+ <>
+ <BugOutlined /> Troubleshooting
+ </>
+ }
+ style={{ marginBottom: 16 }}
+ >
+ <Paragraph type="secondary">
+ Common error messages you may encounter when connecting to or
querying{' '}
+ {name}, along with their causes and solutions.
+ </Paragraph>
+ <Collapse accordion>
+ {sortedCategories.map((category) => (
+ <Panel
+ header={
+ <span>
+ <Tag color={categoryColors[category] || 'default'}>
+ {category}
+ </Tag>
+ {errorsByCategory[category].length} error
+ {errorsByCategory[category].length !== 1 ? 's' : ''}
+ </span>
+ }
+ key={category}
+ >
+ {errorsByCategory[category].map((error, idx) => (
+ <div
+ key={idx}
+ style={{
+ marginBottom:
+ idx < errorsByCategory[category].length - 1 ? 16 : 0,
+ paddingBottom:
+ idx < errorsByCategory[category].length - 1 ? 16 : 0,
+ borderBottom:
+ idx < errorsByCategory[category].length - 1
+ ? '1px solid var(--ifm-color-emphasis-200)'
+ : 'none',
+ }}
+ >
+ <div style={{ marginBottom: 8 }}>
+ <Text strong>{error.description || error.error_type}</Text>
+ </div>
+ <Alert
+ message={error.message_template}
+ type="error"
+ style={{ marginBottom: 8 }}
+ />
+ {error.invalid_fields && error.invalid_fields.length > 0 && (
+ <div style={{ marginBottom: 8 }}>
+ <Text type="secondary">Check these fields: </Text>
+ {error.invalid_fields.map((field) => (
+ <Tag key={field} color="warning">
+ {field}
+ </Tag>
+ ))}
+ </div>
+ )}
+ {error.issue_codes && error.issue_codes.length > 0 && (
+ <div>
+ <Text type="secondary">Related issue codes: </Text>
+ {error.issue_codes.map((code) => (
+ <Tag key={code}>
+ <a
+
href={`/docs/using-superset/issue-codes#issue-${code}`}
+ style={{ color: 'inherit' }}
+ >
+ Issue {code}
+ </a>
+ </Tag>
+ ))}
+ </div>
+ )}
+ </div>
+ ))}
+ </Panel>
+ ))}
+ </Collapse>
+ </Card>
+ );
+ };
+
return (
<div
className="database-page"
@@ -556,6 +683,9 @@ const DatabasePage: React.FC<DatabasePageProps> = ({
database, name }) => {
{/* Time Grains */}
{renderTimeGrains()}
+ {/* Troubleshooting / Custom Errors */}
+ {renderTroubleshooting()}
+
{/* Compatible Databases */}
{renderCompatibleDatabases()}
diff --git a/docs/src/components/databases/types.ts
b/docs/src/components/databases/types.ts
index 698c93e2cc..d1ad59e74b 100644
--- a/docs/src/components/databases/types.ts
+++ b/docs/src/components/databases/types.ts
@@ -86,6 +86,17 @@ export interface CompatibleDatabase {
docs_url?: string;
}
+export interface CustomError {
+ error_type: string; // e.g., "CONNECTION_INVALID_USERNAME_ERROR"
+ message_template: string; // e.g., 'The username "%(username)s" does not
exist.'
+ regex_pattern?: string; // The regex pattern that matches this error
(optional, for reference)
+ regex_name?: string; // The name of the regex constant (e.g.,
"CONNECTION_INVALID_USERNAME_REGEX")
+ invalid_fields?: string[]; // Fields that are invalid, e.g., ["username",
"password"]
+ issue_codes?: number[]; // Related issue codes from ISSUE_CODES mapping
+ category?: string; // Error category: "Authentication",
"Connection", "Query", etc.
+ description?: string; // Human-readable short description of the
error type
+}
+
export interface DatabaseDocumentation {
description?: string;
logo?: string;
@@ -111,6 +122,7 @@ export interface DatabaseDocumentation {
sqlalchemy_docs_url?: string;
advanced_features?: Record<string, string>;
compatible_databases?: CompatibleDatabase[];
+ custom_errors?: CustomError[]; // Database-specific error messages and
troubleshooting info
}
export interface TimeGrains {
diff --git a/docs/src/data/databases.json b/docs/src/data/databases.json
index 35e91f79a9..0605694146 100644
--- a/docs/src/data/databases.json
+++ b/docs/src/data/databases.json
@@ -1,5 +1,5 @@
{
- "generated": "2026-01-21T21:46:41.044Z",
+ "generated": "2026-01-21T23:22:58.314Z",
"statistics": {
"totalDatabases": 67,
"withDocumentation": 67,
@@ -333,7 +333,19 @@
}
}
],
- "notes": "URL-encode special characters in s3_staging_dir (e.g., s3://
becomes s3%3A//)."
+ "notes": "URL-encode special characters in s3_staging_dir (e.g., s3://
becomes s3%3A//).",
+ "custom_errors": [
+ {
+ "regex_name": "SYNTAX_ERROR_REGEX",
+ "message_template": "Please check your query for syntax errors at
or near \"%(syntax_error)s\". Then, try running your query again.",
+ "error_type": "SYNTAX_ERROR",
+ "category": "Query",
+ "description": "SQL syntax error",
+ "issue_codes": [
+ 1030
+ ]
+ }
+ ]
},
"time_grains": {},
"score": 0,
@@ -516,7 +528,62 @@
"warnings": [
"Google BigQuery Python SDK is not compatible with gevent. Use a
worker type other than gevent when deploying with gunicorn."
],
- "docs_url": "https://github.com/googleapis/python-bigquery-sqlalchemy"
+ "docs_url": "https://github.com/googleapis/python-bigquery-sqlalchemy",
+ "custom_errors": [
+ {
+ "regex_name": "CONNECTION_DATABASE_PERMISSIONS_REGEX",
+ "message_template": "Unable to connect. Verify that the following
roles are set on the service account: \"BigQuery Data Viewer\", \"BigQuery
Metadata Viewer\", \"BigQuery Job User\" and the following permissions are set
\"bigquery.readsessions.create\", \"bigquery.readsessions.getData\"",
+ "error_type": "CONNECTION_DATABASE_PERMISSIONS_ERROR",
+ "category": "Permissions",
+ "description": "Insufficient permissions",
+ "issue_codes": [
+ 1017
+ ]
+ },
+ {
+ "regex_name": "TABLE_DOES_NOT_EXIST_REGEX",
+ "message_template": "The table \"%(table)s\" does not exist. A
valid table must be used to run this query.",
+ "error_type": "TABLE_DOES_NOT_EXIST_ERROR",
+ "category": "Query",
+ "description": "Table not found",
+ "issue_codes": [
+ 1003,
+ 1005
+ ]
+ },
+ {
+ "regex_name": "COLUMN_DOES_NOT_EXIST_REGEX",
+ "message_template": "We can't seem to resolve column
\"%(column)s\" at line %(location)s.",
+ "error_type": "COLUMN_DOES_NOT_EXIST_ERROR",
+ "category": "Query",
+ "description": "Column not found",
+ "issue_codes": [
+ 1003,
+ 1004
+ ]
+ },
+ {
+ "regex_name": "SCHEMA_DOES_NOT_EXIST_REGEX",
+ "message_template": "The schema \"%(schema)s\" does not exist. A
valid schema must be used to run this query.",
+ "error_type": "SCHEMA_DOES_NOT_EXIST_ERROR",
+ "category": "Query",
+ "description": "Schema not found",
+ "issue_codes": [
+ 1003,
+ 1016
+ ]
+ },
+ {
+ "regex_name": "SYNTAX_ERROR_REGEX",
+ "message_template": "Please check your query for syntax errors at
or near \"%(syntax_error)s\". Then, try running your query again.",
+ "error_type": "SYNTAX_ERROR",
+ "category": "Query",
+ "description": "SQL syntax error",
+ "issue_codes": [
+ 1030
+ ]
+ }
+ ]
},
"time_grains": {},
"score": 0,
@@ -1214,6 +1281,120 @@
"is_recommended": true,
"notes": "Uses PostgreSQL wire protocol."
}
+ ],
+ "custom_errors": [
+ {
+ "message_template": "Incorrect username or password.",
+ "error_type": "CONNECTION_INVALID_USERNAME_ERROR",
+ "category": "Authentication",
+ "description": "Invalid username",
+ "issue_codes": [
+ 1012
+ ],
+ "invalid_fields": [
+ "username",
+ "password"
+ ]
+ },
+ {
+ "message_template": "Please enter a password.",
+ "error_type": "CONNECTION_ACCESS_DENIED_ERROR",
+ "category": "Authentication",
+ "description": "Access denied",
+ "issue_codes": [
+ 1014,
+ 1015
+ ],
+ "invalid_fields": [
+ "password"
+ ]
+ },
+ {
+ "message_template": "Hostname \"%(hostname)s\" cannot be
resolved.",
+ "error_type": "CONNECTION_INVALID_HOSTNAME_ERROR",
+ "category": "Connection",
+ "description": "Invalid hostname",
+ "issue_codes": [
+ 1007
+ ],
+ "invalid_fields": [
+ "host"
+ ]
+ },
+ {
+ "message_template": "Server refused the connection: check hostname
and port.",
+ "error_type": "CONNECTION_PORT_CLOSED_ERROR",
+ "category": "Connection",
+ "description": "Port closed or refused",
+ "issue_codes": [
+ 1008
+ ],
+ "invalid_fields": [
+ "host",
+ "port"
+ ]
+ },
+ {
+ "message_template": "Unable to connect to database
\"%(database)s\"",
+ "error_type": "CONNECTION_UNKNOWN_DATABASE_ERROR",
+ "category": "Connection",
+ "description": "Unknown database",
+ "issue_codes": [
+ 1015
+ ],
+ "invalid_fields": [
+ "database"
+ ]
+ },
+ {
+ "message_template": "Unable to connect to database
\"%(database)s\": database does not exist or insufficient permissions",
+ "error_type": "CONNECTION_DATABASE_PERMISSIONS_ERROR",
+ "category": "Permissions",
+ "description": "Insufficient permissions",
+ "issue_codes": [
+ 1017
+ ],
+ "invalid_fields": [
+ "database"
+ ]
+ },
+ {
+ "message_template": "Please check your query for syntax errors at
or near \"%(err)s\". Then, try running your query again.",
+ "error_type": "SYNTAX_ERROR",
+ "category": "Query",
+ "description": "SQL syntax error",
+ "issue_codes": [
+ 1030
+ ]
+ },
+ {
+ "message_template": "Column \"%(column)s\" not found in
\"%(view)s\".",
+ "error_type": "COLUMN_DOES_NOT_EXIST_ERROR",
+ "category": "Query",
+ "description": "Column not found",
+ "issue_codes": [
+ 1003,
+ 1004
+ ]
+ },
+ {
+ "message_template": "Invalid aggregation expression.",
+ "error_type": "SYNTAX_ERROR",
+ "category": "Query",
+ "description": "SQL syntax error",
+ "issue_codes": [
+ 1030
+ ]
+ },
+ {
+ "message_template": "\"%(exp)s\" is neither an aggregation
function nor appears in the GROUP BY clause.",
+ "error_type": "SYNTAX_ERROR",
+ "category": "Query",
+ "description": "SQL syntax error",
+ "issue_codes": [
+ 1030
+ ]
+ }
]
},
"time_grains": {
@@ -1313,6 +1494,73 @@
"APACHE_PROJECTS",
"ANALYTICAL_DATABASES",
"OPEN_SOURCE"
+ ],
+ "custom_errors": [
+ {
+ "regex_name": "CONNECTION_ACCESS_DENIED_REGEX",
+ "message_template": "Either the username \"%(username)s\" or the
password is incorrect.",
+ "error_type": "CONNECTION_ACCESS_DENIED_ERROR",
+ "category": "Authentication",
+ "description": "Access denied",
+ "issue_codes": [
+ 1014,
+ 1015
+ ],
+ "invalid_fields": [
+ "username",
+ "password"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_INVALID_HOSTNAME_REGEX",
+ "message_template": "Unknown Doris server host \"%(hostname)s\".",
+ "error_type": "CONNECTION_INVALID_HOSTNAME_ERROR",
+ "category": "Connection",
+ "description": "Invalid hostname",
+ "issue_codes": [
+ 1007
+ ],
+ "invalid_fields": [
+ "host"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_HOST_DOWN_REGEX",
+ "message_template": "The host \"%(hostname)s\" might be down and
can't be reached.",
+ "error_type": "CONNECTION_HOST_DOWN_ERROR",
+ "category": "Connection",
+ "description": "Host unreachable",
+ "issue_codes": [
+ 1009
+ ],
+ "invalid_fields": [
+ "host",
+ "port"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_UNKNOWN_DATABASE_REGEX",
+ "message_template": "Unable to connect to database
\"%(database)s\".",
+ "error_type": "CONNECTION_UNKNOWN_DATABASE_ERROR",
+ "category": "Connection",
+ "description": "Unknown database",
+ "issue_codes": [
+ 1015
+ ],
+ "invalid_fields": [
+ "database"
+ ]
+ },
+ {
+ "regex_name": "SYNTAX_ERROR_REGEX",
+ "message_template": "Please check your query for syntax errors
near \"%(server_error)s\". Then, try running your query again.",
+ "error_type": "SYNTAX_ERROR",
+ "category": "Query",
+ "description": "SQL syntax error",
+ "issue_codes": [
+ 1030
+ ]
+ }
]
},
"time_grains": {
@@ -1650,6 +1898,19 @@
"HOSTED_OPEN_SOURCE"
]
}
+ ],
+ "custom_errors": [
+ {
+ "regex_name": "COLUMN_DOES_NOT_EXIST_REGEX",
+ "message_template": "We can't seem to resolve the column
\"%(column_name)s\"",
+ "error_type": "COLUMN_DOES_NOT_EXIST_ERROR",
+ "category": "Query",
+ "description": "Column not found",
+ "issue_codes": [
+ 1003,
+ 1004
+ ]
+ }
]
},
"time_grains": {
@@ -1727,7 +1988,20 @@
"database": "MotherDuck database name",
"token": "Service token from MotherDuck dashboard"
},
- "docs_url": "https://motherduck.com/docs/getting-started/"
+ "docs_url": "https://motherduck.com/docs/getting-started/",
+ "custom_errors": [
+ {
+ "regex_name": "COLUMN_DOES_NOT_EXIST_REGEX",
+ "message_template": "We can't seem to resolve the column
\"%(column_name)s\"",
+ "error_type": "COLUMN_DOES_NOT_EXIST_ERROR",
+ "category": "Query",
+ "description": "Column not found",
+ "issue_codes": [
+ 1003,
+ 1004
+ ]
+ }
+ ]
},
"time_grains": {},
"score": 0,
@@ -2159,7 +2433,19 @@
"CLOUD_GCP",
"HOSTED_OPEN_SOURCE"
],
- "install_instructions": "pip install \"apache-superset[gsheets]\""
+ "install_instructions": "pip install \"apache-superset[gsheets]\"",
+ "custom_errors": [
+ {
+ "regex_name": "SYNTAX_ERROR_REGEX",
+ "message_template": "Please check your query for syntax errors
near \"%(server_error)s\". Then, try running your query again.",
+ "error_type": "SYNTAX_ERROR",
+ "category": "Query",
+ "description": "SQL syntax error",
+ "issue_codes": [
+ 1030
+ ]
+ }
+ ]
},
"time_grains": {
"SECOND": true,
@@ -2755,7 +3041,50 @@
"notes": "Connection string must be URL-encoded. Special
characters like @ need encoding."
}
],
- "docs_url":
"https://docs.sqlalchemy.org/en/20/core/engines.html#escaping-special-characters-such-as-signs-in-passwords"
+ "docs_url":
"https://docs.sqlalchemy.org/en/20/core/engines.html#escaping-special-characters-such-as-signs-in-passwords",
+ "custom_errors": [
+ {
+ "regex_name": "CONNECTION_ACCESS_DENIED_REGEX",
+ "message_template": "Either the username \"%(username)s\",
password, or database name \"%(database)s\" is incorrect.",
+ "error_type": "CONNECTION_ACCESS_DENIED_ERROR",
+ "category": "Authentication",
+ "description": "Access denied",
+ "issue_codes": [
+ 1014,
+ 1015
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_INVALID_HOSTNAME_REGEX",
+ "message_template": "The hostname \"%(hostname)s\" cannot be
resolved.",
+ "error_type": "CONNECTION_INVALID_HOSTNAME_ERROR",
+ "category": "Connection",
+ "description": "Invalid hostname",
+ "issue_codes": [
+ 1007
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_PORT_CLOSED_REGEX",
+ "message_template": "Port %(port)s on hostname \"%(hostname)s\"
refused the connection.",
+ "error_type": "CONNECTION_PORT_CLOSED_ERROR",
+ "category": "Connection",
+ "description": "Port closed or refused",
+ "issue_codes": [
+ 1008
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_HOST_DOWN_REGEX",
+ "message_template": "The host \"%(hostname)s\" might be down, and
can't be reached on port %(port)s.",
+ "error_type": "CONNECTION_HOST_DOWN_ERROR",
+ "category": "Connection",
+ "description": "Host unreachable",
+ "issue_codes": [
+ 1009
+ ]
+ }
+ ]
},
"time_grains": {
"SECOND": true,
@@ -2828,6 +3157,49 @@
"CLOUD_DATA_WAREHOUSES",
"ANALYTICAL_DATABASES",
"PROPRIETARY"
+ ],
+ "custom_errors": [
+ {
+ "regex_name": "CONNECTION_ACCESS_DENIED_REGEX",
+ "message_template": "Either the username \"%(username)s\",
password, or database name \"%(database)s\" is incorrect.",
+ "error_type": "CONNECTION_ACCESS_DENIED_ERROR",
+ "category": "Authentication",
+ "description": "Access denied",
+ "issue_codes": [
+ 1014,
+ 1015
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_INVALID_HOSTNAME_REGEX",
+ "message_template": "The hostname \"%(hostname)s\" cannot be
resolved.",
+ "error_type": "CONNECTION_INVALID_HOSTNAME_ERROR",
+ "category": "Connection",
+ "description": "Invalid hostname",
+ "issue_codes": [
+ 1007
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_PORT_CLOSED_REGEX",
+ "message_template": "Port %(port)s on hostname \"%(hostname)s\"
refused the connection.",
+ "error_type": "CONNECTION_PORT_CLOSED_ERROR",
+ "category": "Connection",
+ "description": "Port closed or refused",
+ "issue_codes": [
+ 1008
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_HOST_DOWN_REGEX",
+ "message_template": "The host \"%(hostname)s\" might be down, and
can't be reached on port %(port)s.",
+ "error_type": "CONNECTION_HOST_DOWN_ERROR",
+ "category": "Connection",
+ "description": "Host unreachable",
+ "issue_codes": [
+ 1009
+ ]
+ }
]
},
"time_grains": {},
@@ -2939,6 +3311,73 @@
"HOSTED_OPEN_SOURCE"
]
}
+ ],
+ "custom_errors": [
+ {
+ "regex_name": "CONNECTION_ACCESS_DENIED_REGEX",
+ "message_template": "Either the username \"%(username)s\" or the
password is incorrect.",
+ "error_type": "CONNECTION_ACCESS_DENIED_ERROR",
+ "category": "Authentication",
+ "description": "Access denied",
+ "issue_codes": [
+ 1014,
+ 1015
+ ],
+ "invalid_fields": [
+ "username",
+ "password"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_INVALID_HOSTNAME_REGEX",
+ "message_template": "Unknown MySQL server host \"%(hostname)s\".",
+ "error_type": "CONNECTION_INVALID_HOSTNAME_ERROR",
+ "category": "Connection",
+ "description": "Invalid hostname",
+ "issue_codes": [
+ 1007
+ ],
+ "invalid_fields": [
+ "host"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_HOST_DOWN_REGEX",
+ "message_template": "The host \"%(hostname)s\" might be down and
can't be reached.",
+ "error_type": "CONNECTION_HOST_DOWN_ERROR",
+ "category": "Connection",
+ "description": "Host unreachable",
+ "issue_codes": [
+ 1009
+ ],
+ "invalid_fields": [
+ "host",
+ "port"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_UNKNOWN_DATABASE_REGEX",
+ "message_template": "Unable to connect to database
\"%(database)s\".",
+ "error_type": "CONNECTION_UNKNOWN_DATABASE_ERROR",
+ "category": "Connection",
+ "description": "Unknown database",
+ "issue_codes": [
+ 1015
+ ],
+ "invalid_fields": [
+ "database"
+ ]
+ },
+ {
+ "regex_name": "SYNTAX_ERROR_REGEX",
+ "message_template": "Please check your query for syntax errors
near \"%(server_error)s\". Then, try running your query again.",
+ "error_type": "SYNTAX_ERROR",
+ "category": "Query",
+ "description": "SQL syntax error",
+ "issue_codes": [
+ 1030
+ ]
+ }
]
},
"time_grains": {
@@ -3068,6 +3507,73 @@
"categories": [
"TRADITIONAL_RDBMS",
"OPEN_SOURCE"
+ ],
+ "custom_errors": [
+ {
+ "regex_name": "CONNECTION_ACCESS_DENIED_REGEX",
+ "message_template": "Either the username \"%(username)s\" or the
password is incorrect.",
+ "error_type": "CONNECTION_ACCESS_DENIED_ERROR",
+ "category": "Authentication",
+ "description": "Access denied",
+ "issue_codes": [
+ 1014,
+ 1015
+ ],
+ "invalid_fields": [
+ "username",
+ "password"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_INVALID_HOSTNAME_REGEX",
+ "message_template": "Unknown OceanBase server host
\"%(hostname)s\".",
+ "error_type": "CONNECTION_INVALID_HOSTNAME_ERROR",
+ "category": "Connection",
+ "description": "Invalid hostname",
+ "issue_codes": [
+ 1007
+ ],
+ "invalid_fields": [
+ "host"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_HOST_DOWN_REGEX",
+ "message_template": "The host \"%(hostname)s\" might be down and
can't be reached.",
+ "error_type": "CONNECTION_HOST_DOWN_ERROR",
+ "category": "Connection",
+ "description": "Host unreachable",
+ "issue_codes": [
+ 1009
+ ],
+ "invalid_fields": [
+ "host",
+ "port"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_UNKNOWN_DATABASE_REGEX",
+ "message_template": "Unable to connect to database
\"%(database)s\".",
+ "error_type": "CONNECTION_UNKNOWN_DATABASE_ERROR",
+ "category": "Connection",
+ "description": "Unknown database",
+ "issue_codes": [
+ 1015
+ ],
+ "invalid_fields": [
+ "database"
+ ]
+ },
+ {
+ "regex_name": "SYNTAX_ERROR_REGEX",
+ "message_template": "Please check your query for syntax errors
near \"%(server_error)s\". Then, try running your query again.",
+ "error_type": "SYNTAX_ERROR",
+ "category": "Query",
+ "description": "SQL syntax error",
+ "issue_codes": [
+ 1030
+ ]
+ }
]
},
"time_grains": {},
@@ -3099,7 +3605,96 @@
"sqlalchemy-ocient"
],
"connection_string":
"ocient://{username}:{password}@{host}:{port}/{database}",
- "install_instructions": "pip install sqlalchemy-ocient"
+ "install_instructions": "pip install sqlalchemy-ocient",
+ "custom_errors": [
+ {
+ "regex_name": "CONNECTION_INVALID_USERNAME_REGEX",
+ "message_template": "The username \"%(username)s\" does not
exist.",
+ "error_type": "CONNECTION_INVALID_USERNAME_ERROR",
+ "category": "Authentication",
+ "description": "Invalid username",
+ "issue_codes": [
+ 1012
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_INVALID_PASSWORD_REGEX",
+ "message_template": "The user/password combination is not valid
(Incorrect password for user).",
+ "error_type": "CONNECTION_INVALID_PASSWORD_ERROR",
+ "category": "Authentication",
+ "description": "Invalid password",
+ "issue_codes": [
+ 1013
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_UNKNOWN_DATABASE_REGEX",
+ "message_template": "Could not connect to database:
\"%(database)s\"",
+ "error_type": "CONNECTION_UNKNOWN_DATABASE_ERROR",
+ "category": "Connection",
+ "description": "Unknown database",
+ "issue_codes": [
+ 1015
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_INVALID_HOSTNAME_REGEX",
+ "message_template": "Could not resolve hostname: \"%(host)s\".",
+ "error_type": "CONNECTION_INVALID_HOSTNAME_ERROR",
+ "category": "Connection",
+ "description": "Invalid hostname",
+ "issue_codes": [
+ 1007
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_INVALID_PORT_ERROR",
+ "message_template": "Port out of range 0-65535",
+ "error_type": "CONNECTION_INVALID_PORT_ERROR"
+ },
+ {
+ "regex_name": "INVALID_CONNECTION_STRING_REGEX",
+ "message_template": "Invalid Connection String: Expecting String
of the form 'ocient://user:pass@host:port/database'.",
+ "error_type": "GENERIC_DB_ENGINE_ERROR",
+ "category": "General",
+ "description": "Database engine error",
+ "issue_codes": [
+ 1002
+ ]
+ },
+ {
+ "regex_name": "SYNTAX_ERROR_REGEX",
+ "message_template": "Syntax Error: %(qualifier)s input
\"%(input)s\" expecting \"%(expected)s",
+ "error_type": "SYNTAX_ERROR",
+ "category": "Query",
+ "description": "SQL syntax error",
+ "issue_codes": [
+ 1030
+ ]
+ },
+ {
+ "regex_name": "TABLE_DOES_NOT_EXIST_REGEX",
+ "message_template": "Table or View \"%(table)s\" does not exist.",
+ "error_type": "TABLE_DOES_NOT_EXIST_ERROR",
+ "category": "Query",
+ "description": "Table not found",
+ "issue_codes": [
+ 1003,
+ 1005
+ ]
+ },
+ {
+ "regex_name": "COLUMN_DOES_NOT_EXIST_REGEX",
+ "message_template": "Invalid reference to column: \"%(column)s\"",
+ "error_type": "COLUMN_DOES_NOT_EXIST_ERROR",
+ "category": "Query",
+ "description": "Column not found",
+ "issue_codes": [
+ 1003,
+ 1004
+ ]
+ }
+ ]
},
"time_grains": {
"SECOND": true,
@@ -3446,6 +4041,124 @@
"HOSTED_OPEN_SOURCE"
]
}
+ ],
+ "custom_errors": [
+ {
+ "regex_name": "CONNECTION_INVALID_USERNAME_REGEX",
+ "message_template": "The username \"%(username)s\" does not
exist.",
+ "error_type": "CONNECTION_INVALID_USERNAME_ERROR",
+ "category": "Authentication",
+ "description": "Invalid username",
+ "issue_codes": [
+ 1012
+ ],
+ "invalid_fields": [
+ "username"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_INVALID_PASSWORD_REGEX",
+ "message_template": "The password provided for username
\"%(username)s\" is incorrect.",
+ "error_type": "CONNECTION_INVALID_PASSWORD_ERROR",
+ "category": "Authentication",
+ "description": "Invalid password",
+ "issue_codes": [
+ 1013
+ ],
+ "invalid_fields": [
+ "username",
+ "password"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_INVALID_PASSWORD_NEEDED_REGEX",
+ "message_template": "Please re-enter the password.",
+ "error_type": "CONNECTION_ACCESS_DENIED_ERROR",
+ "category": "Authentication",
+ "description": "Access denied",
+ "issue_codes": [
+ 1014,
+ 1015
+ ],
+ "invalid_fields": [
+ "password"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_INVALID_HOSTNAME_REGEX",
+ "message_template": "The hostname \"%(hostname)s\" cannot be
resolved.",
+ "error_type": "CONNECTION_INVALID_HOSTNAME_ERROR",
+ "category": "Connection",
+ "description": "Invalid hostname",
+ "issue_codes": [
+ 1007
+ ],
+ "invalid_fields": [
+ "host"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_PORT_CLOSED_REGEX",
+ "message_template": "Port %(port)s on hostname \"%(hostname)s\"
refused the connection.",
+ "error_type": "CONNECTION_PORT_CLOSED_ERROR",
+ "category": "Connection",
+ "description": "Port closed or refused",
+ "issue_codes": [
+ 1008
+ ],
+ "invalid_fields": [
+ "host",
+ "port"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_HOST_DOWN_REGEX",
+ "message_template": "The host \"%(hostname)s\" might be down, and
can't be reached on port %(port)s.",
+ "error_type": "CONNECTION_HOST_DOWN_ERROR",
+ "category": "Connection",
+ "description": "Host unreachable",
+ "issue_codes": [
+ 1009
+ ],
+ "invalid_fields": [
+ "host",
+ "port"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_UNKNOWN_DATABASE_REGEX",
+ "message_template": "Unable to connect to database
\"%(database)s\".",
+ "error_type": "CONNECTION_UNKNOWN_DATABASE_ERROR",
+ "category": "Connection",
+ "description": "Unknown database",
+ "issue_codes": [
+ 1015
+ ],
+ "invalid_fields": [
+ "database"
+ ]
+ },
+ {
+ "regex_name": "COLUMN_DOES_NOT_EXIST_REGEX",
+ "message_template": "We can't seem to resolve the column
\"%(column_name)s\" at line %(location)s.",
+ "error_type": "COLUMN_DOES_NOT_EXIST_ERROR",
+ "category": "Query",
+ "description": "Column not found",
+ "issue_codes": [
+ 1003,
+ 1004
+ ]
+ },
+ {
+ "regex_name": "SYNTAX_ERROR_REGEX",
+ "message_template": "Please check your query for syntax errors at
or near \"%(syntax_error)s\". Then, try running your query again.",
+ "error_type": "SYNTAX_ERROR",
+ "category": "Query",
+ "description": "SQL syntax error",
+ "issue_codes": [
+ 1030
+ ]
+ }
]
},
"time_grains": {
@@ -3515,6 +4228,92 @@
"connection_string": "presto://{hostname}:{port}/{database}",
"is_recommended": true
}
+ ],
+ "custom_errors": [
+ {
+ "regex_name": "COLUMN_DOES_NOT_EXIST_REGEX",
+ "message_template": "We can't seem to resolve the column
\"%(column_name)s\" at line %(location)s.",
+ "error_type": "COLUMN_DOES_NOT_EXIST_ERROR",
+ "category": "Query",
+ "description": "Column not found",
+ "issue_codes": [
+ 1003,
+ 1004
+ ]
+ },
+ {
+ "regex_name": "TABLE_DOES_NOT_EXIST_REGEX",
+ "message_template": "The table \"%(table_name)s\" does not exist.
A valid table must be used to run this query.",
+ "error_type": "TABLE_DOES_NOT_EXIST_ERROR",
+ "category": "Query",
+ "description": "Table not found",
+ "issue_codes": [
+ 1003,
+ 1005
+ ]
+ },
+ {
+ "regex_name": "SCHEMA_DOES_NOT_EXIST_REGEX",
+ "message_template": "The schema \"%(schema_name)s\" does not
exist. A valid schema must be used to run this query.",
+ "error_type": "SCHEMA_DOES_NOT_EXIST_ERROR",
+ "category": "Query",
+ "description": "Schema not found",
+ "issue_codes": [
+ 1003,
+ 1016
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_ACCESS_DENIED_REGEX",
+ "message_template": "Either the username \"%(username)s\" or the
password is incorrect.",
+ "error_type": "CONNECTION_ACCESS_DENIED_ERROR",
+ "category": "Authentication",
+ "description": "Access denied",
+ "issue_codes": [
+ 1014,
+ 1015
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_INVALID_HOSTNAME_REGEX",
+ "message_template": "The hostname \"%(hostname)s\" cannot be
resolved.",
+ "error_type": "CONNECTION_INVALID_HOSTNAME_ERROR",
+ "category": "Connection",
+ "description": "Invalid hostname",
+ "issue_codes": [
+ 1007
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_HOST_DOWN_REGEX",
+ "message_template": "The host \"%(hostname)s\" might be down, and
can't be reached on port %(port)s.",
+ "error_type": "CONNECTION_HOST_DOWN_ERROR",
+ "category": "Connection",
+ "description": "Host unreachable",
+ "issue_codes": [
+ 1009
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_PORT_CLOSED_REGEX",
+ "message_template": "Port %(port)s on hostname \"%(hostname)s\"
refused the connection.",
+ "error_type": "CONNECTION_PORT_CLOSED_ERROR",
+ "category": "Connection",
+ "description": "Port closed or refused",
+ "issue_codes": [
+ 1008
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_UNKNOWN_DATABASE_ERROR",
+ "message_template": "Unable to connect to catalog named
\"%(catalog_name)s\".",
+ "error_type": "CONNECTION_UNKNOWN_DATABASE_ERROR",
+ "category": "Connection",
+ "description": "Unknown database",
+ "issue_codes": [
+ 1015
+ ]
+ }
]
},
"time_grains": {
@@ -3625,6 +4424,77 @@
}
}
}
+ ],
+ "custom_errors": [
+ {
+ "regex_name": "CONNECTION_ACCESS_DENIED_REGEX",
+ "message_template": "Either the username \"%(username)s\" or the
password is incorrect.",
+ "error_type": "CONNECTION_ACCESS_DENIED_ERROR",
+ "category": "Authentication",
+ "description": "Access denied",
+ "issue_codes": [
+ 1014,
+ 1015
+ ],
+ "invalid_fields": [
+ "username",
+ "password"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_INVALID_HOSTNAME_REGEX",
+ "message_template": "The hostname \"%(hostname)s\" cannot be
resolved.",
+ "error_type": "CONNECTION_INVALID_HOSTNAME_ERROR",
+ "category": "Connection",
+ "description": "Invalid hostname",
+ "issue_codes": [
+ 1007
+ ],
+ "invalid_fields": [
+ "host"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_PORT_CLOSED_REGEX",
+ "message_template": "Port %(port)s on hostname \"%(hostname)s\"
refused the connection.",
+ "error_type": "CONNECTION_PORT_CLOSED_ERROR",
+ "category": "Connection",
+ "description": "Port closed or refused",
+ "issue_codes": [
+ 1008
+ ],
+ "invalid_fields": [
+ "host",
+ "port"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_HOST_DOWN_REGEX",
+ "message_template": "The host \"%(hostname)s\" might be down, and
can't be reached on port %(port)s.",
+ "error_type": "CONNECTION_HOST_DOWN_ERROR",
+ "category": "Connection",
+ "description": "Host unreachable",
+ "issue_codes": [
+ 1009
+ ],
+ "invalid_fields": [
+ "host",
+ "port"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_UNKNOWN_DATABASE_REGEX",
+ "message_template": "We were unable to connect to your database
named \"%(database)s\". Please verify your database name and try again.",
+ "error_type": "CONNECTION_UNKNOWN_DATABASE_ERROR",
+ "category": "Connection",
+ "description": "Unknown database",
+ "issue_codes": [
+ 1015
+ ],
+ "invalid_fields": [
+ "database"
+ ]
+ }
]
},
"time_grains": {},
@@ -3858,7 +4728,29 @@
}
],
"notes": "Schema is not required in connection string. Ensure user has
privileges for all databases/schemas/tables/views/warehouses.",
- "docs_url":
"https://docs.snowflake.com/en/user-guide/key-pair-auth.html"
+ "docs_url":
"https://docs.snowflake.com/en/user-guide/key-pair-auth.html",
+ "custom_errors": [
+ {
+ "regex_name": "OBJECT_DOES_NOT_EXIST_REGEX",
+ "message_template": "%(object)s does not exist in this database.",
+ "error_type": "OBJECT_DOES_NOT_EXIST_ERROR",
+ "category": "Query",
+ "description": "Object not found",
+ "issue_codes": [
+ 1029
+ ]
+ },
+ {
+ "regex_name": "SYNTAX_ERROR_REGEX",
+ "message_template": "Please check your query for syntax errors at
or near \"%(syntax_error)s\". Then, try running your query again.",
+ "error_type": "SYNTAX_ERROR",
+ "category": "Query",
+ "description": "SQL syntax error",
+ "issue_codes": [
+ 1030
+ ]
+ }
+ ]
},
"time_grains": {
"SECOND": true,
@@ -4039,7 +4931,20 @@
],
"pypi_packages": [],
"connection_string":
"sqlite:///path/to/file.db?check_same_thread=false",
- "notes": "No additional library needed. SQLite is bundled with Python."
+ "notes": "No additional library needed. SQLite is bundled with
Python.",
+ "custom_errors": [
+ {
+ "regex_name": "COLUMN_DOES_NOT_EXIST_REGEX",
+ "message_template": "We can't seem to resolve the column
\"%(column_name)s\"",
+ "error_type": "COLUMN_DOES_NOT_EXIST_ERROR",
+ "category": "Query",
+ "description": "Column not found",
+ "issue_codes": [
+ 1003,
+ 1004
+ ]
+ }
+ ]
},
"time_grains": {
"SECOND": true,
@@ -4183,6 +5088,36 @@
},
"docs_url": "https://docs.celerdata.com/"
}
+ ],
+ "custom_errors": [
+ {
+ "regex_name": "CONNECTION_ACCESS_DENIED_REGEX",
+ "message_template": "Either the username \"%(username)s\" or the
password is incorrect.",
+ "error_type": "CONNECTION_ACCESS_DENIED_ERROR",
+ "category": "Authentication",
+ "description": "Access denied",
+ "issue_codes": [
+ 1014,
+ 1015
+ ],
+ "invalid_fields": [
+ "username",
+ "password"
+ ]
+ },
+ {
+ "regex_name": "CONNECTION_UNKNOWN_DATABASE_REGEX",
+ "message_template": "Unable to connect to database
\"%(database)s\".",
+ "error_type": "CONNECTION_UNKNOWN_DATABASE_ERROR",
+ "category": "Connection",
+ "description": "Unknown database",
+ "issue_codes": [
+ 1015
+ ],
+ "invalid_fields": [
+ "database"
+ ]
+ }
]
},
"time_grains": {