Unable to rename a directory named space character using ADLS Gen2 REST API

Juan Carlos Fernández Umaña 25 Reputation points
2025-04-03T17:20:30.6833333+00:00

The rename operation fails when the source directory contains a space in its name.

I've been trying to understand why this happens. In my Golang code, I have multiple test cases, and the rename operation consistently fails when the directory name contains spaces. The strange thing is that creating a folder with spaces works perfectly fine, but renaming it results in an error.

I also tried replacing the space with %20 in the URI, but that didn’t work either—instead, it saves the folder name with the %20 symbol rather than interpreting it as a space.

I receive the following error message:

RESPONSE 400: The source URI is invalid.

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake"
	"github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/directory"
)

func handleError(err error) {
	if err != nil {
		log.Println(err.Error())
	}
}

func main() {
	// Examples
	// 1. Rename a directory without space to a directory without space (PASSED)
	renameDirectory("oldDir01", "newDir01")

	// 2. Rename a directory without space to a directory with space (PASSED)
	renameDirectory("oldDir02", "new Dir02")

	// 3. Rename a directory with space to a directory without space (FAILED) --> RESPONSE 400: The source URI is invalid.
	// Note: The "old Dir" is created successfully, but the rename fails.
	renameDirectory("old Dir03", "newDir03")

	// 4. Raname a directory with parent directory without space (PASSED)
	renameDirectory("oldDir/subDir04", "oldDir/newSubDir04")

	// 5. Rename a directory with parent directory with space (FAILED) --> RESPONSE 400: The source URI is invalid.
	// Note: The "old Dir/subDir" is created successfully, but the rename fails.
	renameDirectory("old Dir/subDir05", "old Dir/newSubDir05")

	// Final Note:
	// The rename operation fails when the source directory contains a space in its name.
	// The error message is not very descriptive, but it seems that the space in the directory name is causing the issue.
	// The rename operation works fine when the source directory does not contain a space in its name.
	// The directory with space in its name is created successfully, but the rename operation fails.
}

func renameDirectory(oldPath, newPath string) {
	accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY")

	containerName := "123456789"
	// Create a directory client
	u := fmt.Sprintf("https://%s.dfs.core.windows.net/%s/%s", accountName, containerName, oldPath)
	fmt.Println("URL: ", u)

	log.Println("Authenticating with account name and key")
	credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey)
	handleError(err)

	dirClient, err := directory.NewClientWithSharedKeyCredential(u, credential, nil)
	handleError(err)

	log.Printf("Creating directory %s\n", oldPath)
	_, err = dirClient.Create(context.Background(), nil)
	handleError(err)

	log.Printf("Renaming directory %s to %s\n", oldPath, newPath)
	_, err = dirClient.Rename(context.Background(), newPath, nil)
	handleError(err)

	log.Println("Directory renamed successfully")
}

Can anyone clarify why this happens?

Azure Data Lake Storage
Azure Data Lake Storage
An Azure service that provides an enterprise-wide hyper-scale repository for big data analytic workloads and is integrated with Azure Blob Storage.
1,554 questions
{count} votes

Accepted answer
  1. Venkatesan S 1,780 Reputation points Microsoft External Staff Moderator
    2025-04-07T08:21:32.4333333+00:00

    Hi @Juan Carlos Fernández Umaña

    The issue is with the SDK, and you have already raised a GitHub issue for it.

    As of now, alternatively, you can use the Azure Data Lake gen2 REST API with a SAS token in your environment.

    In my environment, I tried exactly what you did with 5 test cases, creating and renaming directories using the REST API and a SAS token with the Go language.

    Code:

    package main
    
    import (
    	"fmt"
    	"log"
    	"net/http"
    	"net/url"
    	"strings"
    	"time"
    )
    
    var (
    	account    = "redacted"
    	fileSystem = "redacted"
    	sasToken   = "Redacted"
    )
    
    func encodePath(path string) string {
    	segments := strings.Split(path, "/")
    	for i, seg := range segments {
    		segments[i] = url.PathEscape(seg)
    	}
    	return strings.Join(segments, "/")
    }
    
    func createDirectory(dir string) {
    	encoded := encodePath(dir)
    	url := fmt.Sprintf("https://%s.dfs.core.windows.net/%s/%s?resource=directory&%s", account, fileSystem, encoded, sasToken)
    
    	req, err := http.NewRequest("PUT", url, nil)
    	if err != nil {
    		log.Fatalf("Failed to create request to create directory: %v", err)
    	}
    	req.Header.Set("x-ms-version", "2021-10-04")
    	req.Header.Set("x-ms-date", time.Now().UTC().Format(http.TimeFormat))
    
    	resp, err := http.DefaultClient.Do(req)
    	if err != nil {
    		log.Fatalf("Create directory request failed: %v", err)
    	}
    	defer resp.Body.Close()
    
    	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
    		fmt.Printf("Created source directory '%s'\n", dir)
    	} else {
    		fmt.Printf("Failed to create directory '%s': %d %s\n", dir, resp.StatusCode, resp.Status)
    	}
    }
    
    func renameDirectory(sourceDir, destDir string) {
    	sourcePath := encodePath(sourceDir)
    	destPath := encodePath(destDir)
    
    	destURL := fmt.Sprintf("https://%s.dfs.core.windows.net/%s/%s?%s", account, fileSystem, destPath, sasToken)
    	sourceWithSAS := fmt.Sprintf("/%s/%s?%s", fileSystem, sourcePath, sasToken)
    
    	req, err := http.NewRequest("PUT", destURL, nil)
    	if err != nil {
    		log.Fatalf("Failed to create rename request: %v", err)
    	}
    	req.Header.Set("x-ms-version", "2021-10-04")
    	req.Header.Set("x-ms-rename-source", sourceWithSAS)
    	req.Header.Set("x-ms-date", time.Now().UTC().Format(http.TimeFormat))
    
    	resp, err := http.DefaultClient.Do(req)
    	if err != nil {
    		log.Fatalf("Rename request failed: %v", err)
    	}
    	defer resp.Body.Close()
    
    	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
    		fmt.Printf(" Renamed '%s' → '%s'\n", sourceDir, destDir)
    	} else {
    		fmt.Printf("Rename failed (%s → %s): %d %s\n", sourceDir, destDir, resp.StatusCode, resp.Status)
    	}
    }
    
    func main() {
    	fmt.Println("---- Starting Rename Tests ----")
    
    	createDirectory("oldDir01")
    	renameDirectory("oldDir01", "newDir01")
    
    	createDirectory("oldDir02")
    	renameDirectory("oldDir02", "new Dir02")
    
    	createDirectory("old Dir03")
    	renameDirectory("old Dir03", "newDir03")
    
    	createDirectory("oldDir/subDir04")
    	renameDirectory("oldDir/subDir04", "oldDir/newSubDir04")
    
    	createDirectory("old Dir/subDir05")
    	renameDirectory("old Dir/subDir05", "old Dir/newSubDir05")
    
    	fmt.Println("---- All Done ----")
    }
    

    Output:

    PS C:\Users\xxx\xxxt\goproject\hello> go run hello.go
    ---- Starting Rename Tests ----
    Created source directory 'oldDir01'
     Renamed 'oldDir01' → 'newDir01'
    Created source directory 'oldDir02'
     Renamed 'oldDir02' → 'new Dir02'
    Created source directory 'old Dir03'
     Renamed 'old Dir03' → 'newDir03'
    Created source directory 'oldDir/subDir04'
     Renamed 'oldDir/subDir04' → 'oldDir/newSubDir04'
    Created source directory 'old Dir/subDir05'
     Renamed 'old Dir/subDir05' → 'old Dir/newSubDir05'
    ---- All Done ----
    

    enter image description here

    Portal:

    enter image description here

    Reference:

    Path - Create - REST API (Azure Storage Services) | Microsoft Learn

    Hope this answer helps! please let us know if you have any further queries. I’m happy to assist you further.

    Please do not forget to "Accept the answer” and “up-vote” wherever the information provided helps you, this can be beneficial to other community members.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.