PostgreSQL raises HV004 when a foreign-data wrapper encounters a data type mismatch between the local foreign table column definition and the remote object's actual data type. This commonly occurs when PostgreSQL foreign table columns are declared with incompatible types or when using FDWs like oracle_fdw where type conversion is not supported. Aligning the column data types between local and remote definitions resolves the error.
HV004 is part of the SQL/MED error class that PostgreSQL raises whenever a foreign-data wrapper (FDW) encounters a data type that cannot be converted or mapped correctly between the local and remote systems. Each FDW (postgres_fdw, oracle_fdw, mysql_fdw, etc.) has its own set of supported data types and conversion rules. When PostgreSQL attempts to use a column with a type that the FDW cannot translate, or when the remote database lacks a compatible data type for the local column definition, the FDW raises HV004 to prevent sending invalid requests across the wire. This safeguard forces you to ensure that foreign table column definitions match not just the names, but also the data types and characteristics of the remote objects. Type mismatches are especially common with Oracle foreign tables, which have stricter type compatibility rules than PostgreSQL-to-PostgreSQL FDW connections.
Connect to your PostgreSQL database and describe the foreign table to see all column names and their declared data types.
-- Display the foreign table structure:
\d+ foreign_schema.foreign_table_name
-- Or query the information schema:
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_schema = 'foreign_schema'
AND table_name = 'foreign_table_name'
ORDER BY ordinal_position;Note the exact data type of each column, especially those that might be problematic (date types, timestamps, numeric types, text-to-number mappings).
Connect directly to the remote database and retrieve the actual column definitions. This is the source of truth for what the FDW must convert.
For Oracle:
CONNECT TO oracle_instance;
DESC remote_table_name;
-- Or:
SELECT column_name, data_type
FROM user_tab_columns
WHERE table_name = 'REMOTE_TABLE_NAME'
ORDER BY column_id;For MySQL:
DESC database_name.remote_table_name;
SHOW FULL COLUMNS FROM database_name.remote_table_name;For PostgreSQL remotes via postgres_fdw:
-- On the remote server:
\d remote_table_nameCompare the remote data types with the types declared in your local foreign table definition.
Cross-reference your remote types with the FDW documentation to identify which types are not supported or require special handling.
Common problematic mappings:
- oracle_fdw: Oracle NUMBER without scale → PostgreSQL numeric; Oracle DATE → PostgreSQL timestamp; Oracle CLOB → not supported locally
- postgres_fdw: Generally forgiving but prefers exact type matches; collation mismatches can cause issues
- mysql_fdw: MySQL ENUM not directly mappable; JSON columns need special handling
Consult the FDW documentation or the conversion table in the handler code to see the exact type mappings supported.
Drop and recreate the foreign table columns using data types that the FDW actually supports. Most commonly, this means changing abstract or incompatible remote types to text or varchar locally and handling conversion in application logic.
-- Drop the foreign table if it has problematic columns:
DROP FOREIGN TABLE IF EXISTS foreign_schema.foreign_table_name;
-- Recreate with compatible types:
CREATE FOREIGN TABLE foreign_schema.foreign_table_name (
id integer,
name text, -- Instead of oracle VARCHAR2, use PostgreSQL text
created_date text, -- Store Oracle DATE as text, convert in app
amount numeric, -- Oracle NUMBER → PostgreSQL numeric
PRIMARY KEY (id)
)
SERVER remote_server_name
OPTIONS (
schema_name 'public',
table_name 'remote_table_name'
);For oracle_fdw specifically, if a column type cannot be mapped, you can declare a "dummy" column with a compatible type and simply not query it:
-- Skip unsupported columns; they will return NULL if queried:
CREATE FOREIGN TABLE foreign_schema.foreign_table_name (
id integer,
name text,
unsupported_clob text -- Marked as text but will not be used
)
SERVER oracle_server
OPTIONS (
schema_name 'SCHEMA',
table_name 'REMOTE_TABLE'
);Run simple SELECT queries to confirm the foreign table now works without HV004 errors.
-- Try a simple SELECT:
SELECT * FROM foreign_schema.foreign_table_name LIMIT 1;
-- Test with a WHERE clause:
SELECT * FROM foreign_schema.foreign_table_name WHERE id = 1;
-- Test an INSERT if your setup allows writes:
INSERT INTO foreign_schema.foreign_table_name (id, name) VALUES (999, 'Test');If queries succeed without HV004, the type mapping is now correct. If you still see HV004 on a different column, repeat steps 2 and 4 for that column.
If many columns had type issues, it may be simpler to drop the entire foreign table and re-run IMPORT FOREIGN SCHEMA. However, note that IMPORT FOREIGN SCHEMA will use the FDW's default type mapping, which might not resolve all compatibility issues.
-- Drop the foreign table:
DROP FOREIGN TABLE IF EXISTS foreign_schema.foreign_table_name;
-- Re-import:
IMPORT FOREIGN SCHEMA public
LIMIT TO (foreign_table_name)
FROM SERVER remote_server_name
INTO foreign_schema;If the re-imported table still has HV004 issues, it means the FDW cannot automatically convert those types, and you must manually adjust the column definitions as shown in Step 4.
HV004 corresponds to SQL/MED error fdw_invalid_data_type, which reflects fundamental limitations in how each FDW handles type conversion. PostgreSQL's postgres_fdw is fairly forgiving and can coerce types on-the-fly, but other FDWs (especially oracle_fdw) are strict: they require exact type compatibility or explicit mappings.
When using oracle_fdw, remember that columns are matched by position, not by name. If you accidentally create a foreign table with columns in a different order than the remote Oracle table, the FDW will try to interpret an Oracle VARCHAR2 as a PostgreSQL timestamp, for example, and immediately raise HV004.
For best results, always query the remote table structure first, then carefully declare the foreign table columns in the same order and with compatible types. Use the FDW's conversion table (usually in its documentation or source code) to verify that your chosen PostgreSQL types can be translated to or from the remote types.
Some FDWs (like oracle_fdw) allow you to declare "dummy" columns for unsupported types as long as you don't query them. This can be useful for importing the schema but leaving certain columns unused in your application.
insufficient columns in unique constraint for partition key
How to fix "insufficient columns in unique constraint for partition key" in PostgreSQL
ERROR 42501: must be owner of table
How to fix "must be owner of table" in PostgreSQL
trigger cannot change partition destination
How to fix "Trigger cannot change partition destination" in PostgreSQL
SSL error: certificate does not match host name
SSL error: certificate does not match host name in PostgreSQL
No SSL connection
No SSL connection to PostgreSQL