This PostgreSQL error occurs when there's a conflict with escape characters in string literals, typically in COPY commands, E'...' strings, or when using backslashes as escape characters. The parser encounters ambiguous or conflicting escape sequences that it cannot resolve.
The PostgreSQL error "2200B: escape_character_conflict" is a data exception error (SQLSTATE class 22) that occurs when the database parser encounters conflicting or ambiguous escape character sequences in string literals. Escape characters in PostgreSQL allow special characters to be included in strings, such as newlines ( ), tabs ( ), or literal quotes ('). The conflict arises when: 1. The same character is used for multiple escaping purposes 2. Escape sequences conflict with the string literal syntax 3. Backslash usage is ambiguous between escape sequences and literal backslashes 4. COPY command delimiters conflict with escape characters This error commonly appears in contexts like: - COPY ... FROM/TO commands with ESCAPE clauses - E'...' strings (escape string constants) - String literals containing backslashes - CSV/TSV data import/export operations The parser cannot determine whether a character should be interpreted as an escape character or as a literal character, leading to this conflict error.
Examine your COPY commands for conflicting escape characters. The most common issue is using the same character for multiple purposes:
-- Problematic: Same character for DELIMITER and ESCAPE
COPY table_name FROM '/path/to/file.csv'
WITH (FORMAT csv, DELIMITER '|', ESCAPE '|');
-- Solution: Use different characters
COPY table_name FROM '/path/to/file.csv'
WITH (FORMAT csv, DELIMITER '|', ESCAPE '\');
-- Also check for QUOTE and ESCAPE conflicts
COPY table_name FROM '/path/to/file.csv'
WITH (FORMAT csv, QUOTE '"', ESCAPE '"'); -- Problematic
COPY table_name FROM '/path/to/file.csv'
WITH (FORMAT csv, QUOTE '"', ESCAPE '\'); -- CorrectRules to follow:
1. ESCAPE character must be different from DELIMITER
2. ESCAPE character must be different from QUOTE (in CSV format)
3. ESCAPE character should not appear in your data as literal content
4. For CSV format, backslash (\) is the default and recommended escape character
For E'...' strings (escape string constants), ensure escape sequences are unambiguous:
-- Problematic: Ambiguous backslash usage
SELECT E'Path: C:\Users\Name\File.txt';
-- Solution 1: Double the backslashes
SELECT E'Path: C:\\Users\\Name\\File.txt';
-- Solution 2: Use dollar-quoted strings instead
SELECT $$Path: C:UsersNameFile.txt$$;
-- Solution 3: Use Unicode escapes carefully
SELECT E'Unicode: αβγ'; -- Greek letters αβγ
-- Common escape sequences:
-- \\ = backslash
-- \' = single quote
-- \" = double quote
-- \b = backspace
-- \f = form feed
-- \n = newline
-- \r = carriage return
-- \t = tab
-- \uXXXX = Unicode character (4 hex digits)
-- \UXXXXXXXX = Unicode character (8 hex digits)
-- \xXX = byte with hex value XX
-- \ooo = byte with octal value oooPostgreSQL has a setting that affects escape handling. Check and adjust if needed:
-- Check current setting
SHOW standard_conforming_strings;
-- When standard_conforming_strings = on (default):
-- Backslashes are treated literally in regular strings
-- Use E'...' for escape sequences
-- When standard_conforming_strings = off:
-- Backslashes are escape characters in all strings
-- Legacy behavior for compatibility
-- If you need legacy behavior:
SET standard_conforming_strings = off;
-- But better to update your code:
-- Change: 'Line 1
Line 2'
-- To: E'Line 1\nLine 2' or $$Line 1
Line 2$$
-- For literal backslashes in data:
INSERT INTO table (path) VALUES (E'C:\\Windows\\System32');
-- Or with standard_conforming_strings = on:
INSERT INTO table (path) VALUES ('C:\Windows\System32');Best practice: Keep standard_conforming_strings = on and use E'...' strings explicitly when you need escape sequences.
If your data contains the escape character as literal content, you need to escape it properly:
-- For COPY commands, preprocess data or change escape character
-- Example: Data contains backslashes, but backslash is escape character
-- Option 1: Change escape character
COPY table_name FROM '/path/to/file.csv'
WITH (FORMAT csv, ESCAPE '~'); -- Use tilde instead of backslash
-- Option 2: Escape the escape characters in your data
-- Before: Column1|Column2WithBackslash|Column3
-- After: Column1|Column2\WithBackslash|Column3
-- Option 3: Use different format
COPY table_name FROM '/path/to/file.txt'
WITH (FORMAT text, DELIMITER '|'); -- TEXT format doesn't use escape by default
-- For programmatic insertion, use parameterized queries
const query = 'INSERT INTO table (data) VALUES ($1)';
const values = ['Text with \ backslash and ' quote'];
await client.query(query, values); -- Driver handles escaping
-- Or escape manually in SQL:
INSERT INTO table (data) VALUES (E'Text with \\ backslash and \' quote');Avoid escape character conflicts by using alternative string literal syntax:
-- 1. Dollar-quoted strings (no escape conflicts)
SELECT $$This string can contain 'quotes', "double quotes", and ackslashes$$;
-- 2. Dollar-quoted with tag
SELECT $tag$This can contain $$ signs too$tag$;
-- 3. Unicode string literals
SELECT U&'d\0061t\+000061'; -- 'data' (hex escapes)
SELECT U&'d\0061t\+000061'; -- Same, with +
-- 4. Two single quotes for literal quote
SELECT 'It''s raining'; -- It's raining
-- 5. For multiline strings, use concatenation
SELECT 'Line 1'
'Line 2'
'Line 3';
-- 6. For complex strings, consider storing in a file and using \include
-- Or use your application layer to handle escapingDollar-quoted strings are particularly useful when you have many special characters or nested quotes.
Test your escape sequences in isolation to identify the conflict:
-- Test individual string literals
SELECT E'\tTab' as test1; -- Should work
SELECT '\tTab' as test2; -- Depends on standard_conforming_strings
-- Test COPY with minimal data
CREATE TEMP TABLE test_escape (id int, data text);
-- Create a test file
\echo '1|Column with \ backslash' > /tmp/test.csv
\echo '2|Column with | pipe' >> /tmp/test.csv
-- Test different escape characters
COPY test_escape FROM '/tmp/test.csv'
WITH (FORMAT csv, DELIMITER '|', ESCAPE '\');
-- Check what was loaded
SELECT * FROM test_escape;
-- Test with problematic data
\echo '3|Data with "quote' > /tmp/test2.csv
COPY test_escape FROM '/tmp/test2.csv'
WITH (FORMAT csv, DELIMITER '|', QUOTE '"', ESCAPE '\');
-- Use \copy for client-side testing (handles file access differently)
\copy test_escape FROM '/tmp/test.csv' WITH (FORMAT csv, DELIMITER '|', ESCAPE '~')### PostgreSQL Escape Handling Evolution
PostgreSQL's escape handling has evolved over versions:
1. Pre-8.2: Backslashes were always escape characters
2. 8.2-8.4: standard_conforming_strings introduced, defaulting to 'off'
3. 9.1+: standard_conforming_strings defaults to 'on' for new databases
4. Future: E'...' syntax may become the only way to use escape sequences
### COPY Command Escape Rules
Different COPY formats have different escape rules:
CSV Format:
- ESCAPE character defaults to \ (same as QUOTE character)
- ESCAPE must be a single one-byte character
- Cannot be same as DELIMITER or QUOTE
- To include ESCAPE character in data, double it
TEXT Format:
- ESCAPE defaults to \ (backslash)
- Used to mark special characters: \N (NULL), \\ (backslash), \t (tab), etc.
- Can be disabled with ESCAPE 'OFF'
BINARY Format:
- No escape character concept
- Raw binary data
### Escape Sequence Priority
When conflicts occur, PostgreSQL applies these priorities:
1. Unicode escapes (\u, \U) have highest priority
2. Hexadecimal escapes (\x)
3. Octal escapes (\ooo)
4. Standard escapes (\n, \t, etc.)
5. Literal character interpretation
### Client-Side vs Server-Side Escaping
Important distinction:
- Server-side escaping: Happens in SQL string literals (E'...', COPY ESCAPE)
- Client-side escaping: Done by database drivers (libpq, JDBC, etc.)
- Application escaping: Your code's responsibility before sending to database
Always use parameterized queries/prepared statements to avoid injection and let the driver handle escaping.
### Common Pitfalls
1. Windows paths: C:\Users\Name needs E'C:\\Users\\Name' or 'C:\Users\Name' (depending on standard_conforming_strings)
2. Regular expressions: Often contain many backslashes, use E'...' or dollar-quoted strings
3. JSON/JSONB: Contains quotes and backslashes, use dollar-quoted strings or parameterized queries
4. Dynamic SQL: Use quote_literal() or format() functions for safe escaping
### Performance Considerations
1. E'...' strings are parsed at query planning time
2. COPY with ESCAPE has minimal overhead
3. Excessive escaping in large datasets can impact import/export performance
4. Consider using \copy for client-side file operations to avoid server file permissions
### Migration Tips
When migrating from other databases or older PostgreSQL:
1. Check standard_conforming_strings setting
2. Audit all string literals for backslash usage
3. Test COPY commands with sample data
4. Consider using dollar-quoted strings for complex literals
5. Update application code to use parameterized queries
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
vacuum failsafe triggered
How to fix "vacuum failsafe triggered" in PostgreSQL
ERROR: syntax error at end of input
Syntax error at end of input in PostgreSQL