[expo-file-system] Trying to use FileSystem.moveAsync() and getting error: File "...." could not be moved to "..."
See original GitHub issueSummary
Trying to move an audio recording created with expo-av from the cache folder to a newly created document directory.
- When the app starts, the document directory is created.
- I’m able to create the recording and retrieve it’s URI.
- When I try to move the file to the new directory, this happens:
Google Pixel 3A device:
File 'file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540lucas%252Faudioly/Audio/recording-8c8cafcd-34e8-45ba-9ffa-b7129cdcf44f.m4a' could not be moved to 'file:///data/user/0/host.exp.exponent/files/ExperienceData/%2540lucas%252Faudioly/my-recordings-folder/'
at node_modules/react-native/Libraries/BatchedBridge/NativeModules.js:103:50 in promiseMethodWrapper
at node_modules/@unimodules/react-native-adapter/build/NativeModulesProxy.native.js:15:23 in moduleName.methodInfo.name
at node_modules/expo-file-system/build/FileSystem.js:69:17 in moveAsync
at node_modules/expo-file-system/build/FileSystem.js:65:7 in moveAsync
at [native code]:null in flushedQueue
at [native code]:null in invokeCallbackAndReturnFlushedQueue
Managed or bare workflow? If you have ios/
or android/
directories in your project, the answer is bare!
managed
What platform(s) does this occur on?
Android
SDK Version (managed workflow only)
42.0.1
Environment
Expo CLI 4.9.1 environment info: System: OS: macOS 11.5 Shell: 5.8 - /bin/zsh Binaries: Node: 14.17.0 - /usr/local/bin/node npm: 6.14.13 - /usr/local/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman SDKs: iOS SDK: Platforms: iOS 14.4, DriverKit 20.2, macOS 11.1, tvOS 14.3, watchOS 7.2 IDEs: Android Studio: 4.2 AI-202.7660.26.42.7351085 Xcode: 12.4/12D4e - /usr/bin/xcodebuild npmPackages: expo: ~42.0.1 => 42.0.3 react: 16.13.1 => 16.13.1 react-dom: 16.13.1 => 16.13.1 react-native: https://github.com/expo/react-native/archive/sdk-42.0.0.tar.gz => 0.63.2 react-native-web: ^0.17.1 => 0.17.1 npmGlobalPackages: expo-cli: 4.9.1 Expo Workflow: managed
Reproducible demo or steps to reproduce from a blank project
- Create new expo managed workflow (blank) project
- Install expo-av
- Install expo-file-system
- Replace code in App.js with:
import React, { useEffect } from "react";
import { Text, View, StyleSheet, Button, SafeAreaView } from "react-native";
import { Audio } from "expo-av";
import * as FileSystem from "expo-file-system";
export default function App() {
const [recording, setRecording] = React.useState();
const [update, setUpdate] = React.useState(false);
const [uri, setUri] = React.useState("");
const recordingsDir = FileSystem.documentDirectory + "my-recordings-folder/";
useEffect(() => {
//Check if the Document Directory was created
const makeDir = async () => {
const dir = await FileSystem.getInfoAsync(recordingsDir);
if (!dir.exists) {
console.log("Recordings Folder directory doesn't exist, creating....");
await FileSystem.makeDirectoryAsync(recordingsDir, {
intermediates: true,
});
}
const dirInfo = await FileSystem.readDirectoryAsync(recordingsDir);
console.log("URI of Recording Folder.:");
console.log(dir);
console.log("Contents of Recording Folder:");
console.log(dirInfo);
};
makeDir();
}, [update]);
async function startRecording() {
try {
console.log("Requesting permissions...");
await Audio.requestPermissionsAsync();
await Audio.setAudioModeAsync({
allowsRecordingIOS: true,
playsInSilentModeIOS: true,
});
console.log("Starting recording...");
const { recording } = await Audio.Recording.createAsync(
Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY
);
setRecording(recording);
console.log("Recording started.");
} catch (err) {
console.error("Failed to start recording", err);
}
}
async function stopRecording() {
console.log("Stopping recording..");
setRecording(undefined);
await recording.stopAndUnloadAsync();
const uri = recording.getURI();
console.log("Recording stopped and stored at:", uri);
try {
await FileSystem.moveAsync({
from: uri,
to: recordingsDir,
});
console.log("Audio was moved! ;)");
} catch (err) {
console.log(err);
}
setUri(uri);
setUpdate(!update);
}
return (
<SafeAreaView style={styles.container}>
<View style={styles.container}>
<Text>{uri}</Text>
<Button
title={recording ? "Stop Recording" : "Start Recording"}
onPress={recording ? stopRecording : startRecording}
/>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
paddingVertical: 24,
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:6 (2 by maintainers)
I was facing the same issue (
File <old-file-path> could not be moved to <new-file-path>
) and was able to resolve it.In OP’s case, they are giving the directory path and not the complete file path. They need to append a filename as well.
So, anyone facing this issue should confirm the following:
from
property actually exists (const {exists} = await FileSystem.getInfoAsync(path);
)to
property is a file path (and not a dir path) and its dir MUST exist (if parent dir doesn’t exist, execute this line:await FileSystem.makeDirectoryAsync(dirPath, { intermediates: true })
)Honestly, this was such a long time ago, I don’t remember what was causing the issue. I think I may have solved it by upgrading to the latest versions, as far as I remember there was a version number missmatch or something. All works for me now.