Skip to content

ORA-29283 Invalid File Operation

Error Text: ORA-29283: invalid file operation or ORA-29283: invalid file operation: [operation details]

The ORA-29283 error occurs when Oracle’s UTL_FILE package encounters an invalid file operation. This can happen due to file permission issues, incorrect paths, file locks, or attempting operations not allowed on the file type.

  • Oracle OS user lacks read/write permissions
  • File owned by different user/group
  • Directory permissions too restrictive
  • Directory object points to non-existent path
  • Path not accessible from database server
  • Network path not mounted or accessible
  • File already open by another process
  • File locked by OS or application
  • Attempting to read a write-only file
  • Writing to a file opened for reading
  • Reading from a file opened for writing
  • Append mode on non-existent file
-- List all directory objects
SELECT directory_name, directory_path
FROM dba_directories
ORDER BY directory_name;
-- Check specific directory
SELECT directory_name, directory_path
FROM dba_directories
WHERE directory_name = UPPER('&directory_name');
-- Check directory privileges
SELECT grantee, privilege
FROM dba_tab_privs
WHERE table_name = UPPER('&directory_name')
AND owner = 'SYS';
-- Test if directory is accessible (creates test file)
DECLARE
v_file UTL_FILE.FILE_TYPE;
v_dir_name VARCHAR2(100) := 'MY_DIR';
BEGIN
-- Try to create a test file
v_file := UTL_FILE.FOPEN(v_dir_name, 'test_access.tmp', 'W');
UTL_FILE.PUT_LINE(v_file, 'Test write successful');
UTL_FILE.FCLOSE(v_file);
-- Try to read it back
v_file := UTL_FILE.FOPEN(v_dir_name, 'test_access.tmp', 'R');
UTL_FILE.FCLOSE(v_file);
-- Clean up
UTL_FILE.FREMOVE(v_dir_name, 'test_access.tmp');
DBMS_OUTPUT.PUT_LINE('Directory access verified successfully');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error: ' || SQLERRM);
IF UTL_FILE.IS_OPEN(v_file) THEN
UTL_FILE.FCLOSE(v_file);
END IF;
END;
/
-- Check if file exists (11g+)
DECLARE
v_exists BOOLEAN;
v_length NUMBER;
v_block_size NUMBER;
BEGIN
UTL_FILE.FGETATTR(
location => 'MY_DIR',
filename => 'myfile.txt',
fexists => v_exists,
file_length => v_length,
block_size => v_block_size
);
IF v_exists THEN
DBMS_OUTPUT.PUT_LINE('File exists, size: ' || v_length || ' bytes');
ELSE
DBMS_OUTPUT.PUT_LINE('File does not exist');
END IF;
END;
/
-- Create directory object pointing to valid path
CREATE OR REPLACE DIRECTORY my_data_dir AS '/u01/app/oracle/data';
-- Grant privileges
GRANT READ, WRITE ON DIRECTORY my_data_dir TO app_user;
-- Verify directory exists at OS level
-- (Run from OS as oracle user):
-- ls -la /u01/app/oracle/data
Terminal window
# Check current permissions
ls -la /u01/app/oracle/data/
# Change ownership to oracle user
chown oracle:oinstall /u01/app/oracle/data/
chown oracle:oinstall /u01/app/oracle/data/*
# Set appropriate permissions
chmod 755 /u01/app/oracle/data/
chmod 644 /u01/app/oracle/data/*.txt
# For write access
chmod 664 /u01/app/oracle/data/output_file.txt
-- Reading a file
DECLARE
v_file UTL_FILE.FILE_TYPE;
v_line VARCHAR2(32767);
BEGIN
-- Open for reading ('R')
v_file := UTL_FILE.FOPEN('MY_DIR', 'input.txt', 'R', 32767);
LOOP
BEGIN
UTL_FILE.GET_LINE(v_file, v_line, 32767);
DBMS_OUTPUT.PUT_LINE(v_line);
EXCEPTION
WHEN NO_DATA_FOUND THEN EXIT;
END;
END LOOP;
UTL_FILE.FCLOSE(v_file);
END;
/
-- Writing a file
DECLARE
v_file UTL_FILE.FILE_TYPE;
BEGIN
-- Open for writing ('W') - overwrites existing
v_file := UTL_FILE.FOPEN('MY_DIR', 'output.txt', 'W', 32767);
UTL_FILE.PUT_LINE(v_file, 'Line 1');
UTL_FILE.PUT_LINE(v_file, 'Line 2');
UTL_FILE.FCLOSE(v_file);
END;
/
-- Appending to a file
DECLARE
v_file UTL_FILE.FILE_TYPE;
BEGIN
-- Open for append ('A')
v_file := UTL_FILE.FOPEN('MY_DIR', 'log.txt', 'A', 32767);
UTL_FILE.PUT_LINE(v_file, TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') || ' - Log entry');
UTL_FILE.FCLOSE(v_file);
END;
/
-- Implement retry logic for locked files
CREATE OR REPLACE PROCEDURE safe_file_write(
p_directory VARCHAR2,
p_filename VARCHAR2,
p_content VARCHAR2,
p_max_retries NUMBER DEFAULT 3
) AS
v_file UTL_FILE.FILE_TYPE;
v_retry_count NUMBER := 0;
v_success BOOLEAN := FALSE;
BEGIN
WHILE v_retry_count < p_max_retries AND NOT v_success LOOP
BEGIN
v_file := UTL_FILE.FOPEN(p_directory, p_filename, 'W', 32767);
UTL_FILE.PUT_LINE(v_file, p_content);
UTL_FILE.FCLOSE(v_file);
v_success := TRUE;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -29283 THEN
v_retry_count := v_retry_count + 1;
IF v_retry_count < p_max_retries THEN
DBMS_LOCK.SLEEP(1); -- Wait 1 second before retry
END IF;
ELSE
RAISE;
END IF;
END;
END LOOP;
IF NOT v_success THEN
RAISE_APPLICATION_ERROR(-20001, 'Could not write to file after ' || p_max_retries || ' attempts');
END IF;
END;
/
-- Complete error handling template
CREATE OR REPLACE PROCEDURE process_file(
p_directory VARCHAR2,
p_filename VARCHAR2
) AS
v_file UTL_FILE.FILE_TYPE;
v_line VARCHAR2(32767);
BEGIN
v_file := UTL_FILE.FOPEN(p_directory, p_filename, 'R', 32767);
LOOP
BEGIN
UTL_FILE.GET_LINE(v_file, v_line, 32767);
-- Process line
EXCEPTION
WHEN NO_DATA_FOUND THEN
EXIT; -- End of file
END;
END LOOP;
UTL_FILE.FCLOSE(v_file);
EXCEPTION
WHEN UTL_FILE.INVALID_PATH THEN
RAISE_APPLICATION_ERROR(-20001, 'Invalid directory path');
WHEN UTL_FILE.INVALID_MODE THEN
RAISE_APPLICATION_ERROR(-20002, 'Invalid file open mode');
WHEN UTL_FILE.INVALID_FILEHANDLE THEN
RAISE_APPLICATION_ERROR(-20003, 'Invalid file handle');
WHEN UTL_FILE.INVALID_OPERATION THEN
RAISE_APPLICATION_ERROR(-20004, 'Invalid file operation');
WHEN UTL_FILE.READ_ERROR THEN
RAISE_APPLICATION_ERROR(-20005, 'File read error');
WHEN UTL_FILE.WRITE_ERROR THEN
RAISE_APPLICATION_ERROR(-20006, 'File write error');
WHEN UTL_FILE.ACCESS_DENIED THEN
RAISE_APPLICATION_ERROR(-20007, 'Access denied to file');
WHEN OTHERS THEN
IF UTL_FILE.IS_OPEN(v_file) THEN
UTL_FILE.FCLOSE(v_file);
END IF;
RAISE;
END;
/
CREATE OR REPLACE PACKAGE file_util AS
PROCEDURE write_file(p_dir VARCHAR2, p_file VARCHAR2, p_content CLOB);
FUNCTION read_file(p_dir VARCHAR2, p_file VARCHAR2) RETURN CLOB;
FUNCTION file_exists(p_dir VARCHAR2, p_file VARCHAR2) RETURN BOOLEAN;
END;
/
CREATE OR REPLACE PACKAGE BODY file_util AS
FUNCTION file_exists(p_dir VARCHAR2, p_file VARCHAR2) RETURN BOOLEAN AS
v_exists BOOLEAN;
v_length NUMBER;
v_block_size NUMBER;
BEGIN
UTL_FILE.FGETATTR(p_dir, p_file, v_exists, v_length, v_block_size);
RETURN v_exists;
END;
PROCEDURE write_file(p_dir VARCHAR2, p_file VARCHAR2, p_content CLOB) AS
v_file UTL_FILE.FILE_TYPE;
v_buffer VARCHAR2(32767);
v_offset NUMBER := 1;
v_chunk_size NUMBER := 32000;
BEGIN
v_file := UTL_FILE.FOPEN(p_dir, p_file, 'W', 32767);
WHILE v_offset <= DBMS_LOB.GETLENGTH(p_content) LOOP
v_buffer := DBMS_LOB.SUBSTR(p_content, v_chunk_size, v_offset);
UTL_FILE.PUT(v_file, v_buffer);
v_offset := v_offset + v_chunk_size;
END LOOP;
UTL_FILE.FCLOSE(v_file);
EXCEPTION
WHEN OTHERS THEN
IF UTL_FILE.IS_OPEN(v_file) THEN UTL_FILE.FCLOSE(v_file); END IF;
RAISE;
END;
FUNCTION read_file(p_dir VARCHAR2, p_file VARCHAR2) RETURN CLOB AS
v_file UTL_FILE.FILE_TYPE;
v_line VARCHAR2(32767);
v_content CLOB;
BEGIN
DBMS_LOB.CREATETEMPORARY(v_content, TRUE);
v_file := UTL_FILE.FOPEN(p_dir, p_file, 'R', 32767);
LOOP
BEGIN
UTL_FILE.GET_LINE(v_file, v_line, 32767);
DBMS_LOB.WRITEAPPEND(v_content, LENGTH(v_line) + 1, v_line || CHR(10));
EXCEPTION
WHEN NO_DATA_FOUND THEN EXIT;
END;
END LOOP;
UTL_FILE.FCLOSE(v_file);
RETURN v_content;
EXCEPTION
WHEN OTHERS THEN
IF UTL_FILE.IS_OPEN(v_file) THEN UTL_FILE.FCLOSE(v_file); END IF;
RAISE;
END;
END file_util;
/
-- Validate before file operations
CREATE OR REPLACE FUNCTION validate_file_access(
p_directory VARCHAR2,
p_filename VARCHAR2,
p_mode VARCHAR2 -- 'R', 'W', or 'A'
) RETURN VARCHAR2 AS
v_exists BOOLEAN;
v_length NUMBER;
v_block_size NUMBER;
v_file UTL_FILE.FILE_TYPE;
BEGIN
-- Check directory exists in Oracle
BEGIN
SELECT 1 INTO v_length
FROM dba_directories
WHERE directory_name = UPPER(p_directory);
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 'ERROR: Directory object does not exist';
END;
-- Check file attributes
UTL_FILE.FGETATTR(p_directory, p_filename, v_exists, v_length, v_block_size);
IF p_mode = 'R' AND NOT v_exists THEN
RETURN 'ERROR: File does not exist for reading';
END IF;
-- Try to open file
BEGIN
v_file := UTL_FILE.FOPEN(p_directory, p_filename, p_mode, 32767);
UTL_FILE.FCLOSE(v_file);
RETURN 'OK: File access validated';
EXCEPTION
WHEN OTHERS THEN
RETURN 'ERROR: ' || SQLERRM;
END;
END;
/
ModeDescriptionFile Must Exist?
RRead textYes
WWrite text (overwrite)No (creates)
AAppend textNo (creates)
RBRead binaryYes
WBWrite binaryNo (creates)
ABAppend binaryNo (creates)
-- Fast directory access test
DECLARE
v_file UTL_FILE.FILE_TYPE;
BEGIN
v_file := UTL_FILE.FOPEN('&directory_name', 'test.tmp', 'W');
UTL_FILE.PUT_LINE(v_file, 'test');
UTL_FILE.FCLOSE(v_file);
UTL_FILE.FREMOVE('&directory_name', 'test.tmp');
DBMS_OUTPUT.PUT_LINE('SUCCESS: Directory is accessible');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('FAILED: ' || SQLERRM);
END;
/
Terminal window
# As oracle user on database server
ls -la $(sqlplus -s / as sysdba <<EOF
SET HEADING OFF FEEDBACK OFF
SELECT directory_path FROM dba_directories WHERE directory_name = 'MY_DIR';
EXIT;
EOF
)