diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
index b62959288ee7684eee86abbce65faab627d8f273..4766a2fe6ae0765efac5ed9666a69e9b215b04f1 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
@@ -4,6 +4,7 @@ import flash from '~/flash';
 import { __, sprintf, s__ } from '~/locale';
 import { GlModal } from '@gitlab/ui';
 import { modalTypes } from '../../constants';
+import { trimPathComponents } from '../../utils';
 
 export default {
   components: {
@@ -51,6 +52,8 @@ export default {
   methods: {
     ...mapActions(['createTempEntry', 'renameEntry']),
     submitForm() {
+      this.entryName = trimPathComponents(this.entryName);
+
       if (this.modalType === modalTypes.rename) {
         if (this.entries[this.entryName] && !this.entries[this.entryName].deleted) {
           flash(
diff --git a/app/assets/javascripts/ide/utils.js b/app/assets/javascripts/ide/utils.js
index e7615be498bbe1656ef49f6657857df1f3c670d0..1ea2b199237e5d9f5bc3429b7841d34e9bb8bf7d 100644
--- a/app/assets/javascripts/ide/utils.js
+++ b/app/assets/javascripts/ide/utils.js
@@ -69,6 +69,12 @@ export const createPathWithExt = p => {
   return `${p.substring(1, p.lastIndexOf('.') + 1 || p.length)}${ext || '.js'}`;
 };
 
+export const trimPathComponents = path =>
+  path
+    .split('/')
+    .map(s => s.trim())
+    .join('/');
+
 export function registerLanguages(def, ...defs) {
   if (defs.length) defs.forEach(lang => registerLanguages(lang));
 
diff --git a/changelogs/unreleased/216509-ide-new-file-trim.yml b/changelogs/unreleased/216509-ide-new-file-trim.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ca7e6cc2eb3ef5bf5de299159fdfb85ea0721752
--- /dev/null
+++ b/changelogs/unreleased/216509-ide-new-file-trim.yml
@@ -0,0 +1,5 @@
+---
+title: Trim whitespace in directory names in the Web IDE
+merge_request: 31305
+author:
+type: fixed
diff --git a/spec/frontend/ide/components/new_dropdown/modal_spec.js b/spec/frontend/ide/components/new_dropdown/modal_spec.js
index b6d4e60ce347209b86b5eda9820394db98b66df0..62a59a76bf4326cededf06f1cc11e784cfbaf61c 100644
--- a/spec/frontend/ide/components/new_dropdown/modal_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/modal_spec.js
@@ -122,9 +122,9 @@ describe('new file modal component', () => {
 
   describe('submitForm', () => {
     let store;
+
     beforeEach(() => {
       store = createStore();
-
       store.state.entries = {
         'test-path/test': {
           name: 'test',
@@ -161,5 +161,15 @@ describe('new file modal component', () => {
 
       expect(createFlash).not.toHaveBeenCalled();
     });
+
+    it('removes leading/trailing found in the new name', () => {
+      vm.open('rename', 'test-path/test');
+
+      vm.entryName = 'test-path /test';
+
+      vm.submitForm();
+
+      expect(vm.entryName).toBe('test-path/test');
+    });
   });
 });
diff --git a/spec/frontend/ide/utils_spec.js b/spec/frontend/ide/utils_spec.js
index 10a31842dd4a059860b5e115b516d8fdadbba29e..ea975500e8da0e697e024c510ec4b8399515bcce 100644
--- a/spec/frontend/ide/utils_spec.js
+++ b/spec/frontend/ide/utils_spec.js
@@ -1,5 +1,5 @@
 import { commitItemIconMap } from '~/ide/constants';
-import { getCommitIconMap, isTextFile, registerLanguages } from '~/ide/utils';
+import { getCommitIconMap, isTextFile, registerLanguages, trimPathComponents } from '~/ide/utils';
 import { decorateData } from '~/ide/stores/utils';
 import { languages } from 'monaco-editor';
 
@@ -104,6 +104,21 @@ describe('WebIDE utils', () => {
     });
   });
 
+  describe('trimPathComponents', () => {
+    it.each`
+      input                           | output
+      ${'example path '}              | ${'example path'}
+      ${'p/somefile '}                | ${'p/somefile'}
+      ${'p /somefile '}               | ${'p/somefile'}
+      ${'p/ somefile '}               | ${'p/somefile'}
+      ${' p/somefile '}               | ${'p/somefile'}
+      ${'p/somefile  .md'}            | ${'p/somefile  .md'}
+      ${'path / to / some/file.doc '} | ${'path/to/some/file.doc'}
+    `('trims all path components in path: "$input"', ({ input, output }) => {
+      expect(trimPathComponents(input)).toEqual(output);
+    });
+  });
+
   describe('registerLanguages', () => {
     let langs;