138

I ran this in debug mode, and I attach an image with the details of the exception. How can I know what went wrong? I was trying to inset data in a table. Can't azure give me more details?

Obs: The storage is on Windows Azure not on my machine. The tables were created, but I get this error when inserting data

enter image description here

// Retrieve the storage account from the connection string.
Microsoft.WindowsAzure.Storage.CloudStorageAccount storageAccount = Microsoft.WindowsAzure.Storage.CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=***;AccountKey=***");

// Create the table client.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

// Create the table if it doesn't exist.
CloudTable table = tableClient.GetTableReference("EmployeeOnlineHistory");
table.CreateIfNotExists();

and here is the insert code:

public static void SetStatus(Employee e, bool value)
{
    try
    {
        // Retrieve the storage account from the connection string.
        Microsoft.WindowsAzure.Storage.CloudStorageAccount storageAccount = Microsoft.WindowsAzure.Storage.CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=###;AccountKey=###");

        // Create the table client.
        CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

        // Create the CloudTable object that represents the "people" table.
        CloudTable table = tableClient.GetTableReference("EmployeeOnlineHistory");

        // Create a new customer entity.

        if (value == true)
        {
            EmployeeOnlineHistory empHistory = new EmployeeOnlineHistory(e.Id);
            empHistory.IsOnline = true;
            empHistory.OnlineTimestamp = DateTime.Now;
            TableOperation insertOperation = TableOperation.Insert(empHistory);
            table.Execute(insertOperation);
        }
        else
        {
            TableQuery<EmployeeOnlineHistory> query = new TableQuery<EmployeeOnlineHistory>()
                .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, e.Id.ToString()));
            EmployeeOnlineHistory entity = table.ExecuteQuery(query).Take(1).FirstOrDefault();

            if ((entity!=null)&&(entity.IsOnline))
            {
                entity.IsOnline = false;
                entity.OfflineTimestamp = DateTime.Now;
                entity.OnlineTime = (entity.OfflineTimestamp - entity.OnlineTimestamp);
                TableOperation updateOperation = TableOperation.Replace(entity);
                table.Execute(updateOperation);
            }
            else
            {
                EmployeeOnlineHistory empHistory = new EmployeeOnlineHistory(e.Id);
                empHistory.IsOnline = false;
                empHistory.OfflineTimestamp = DateTime.Now;
                TableOperation insertOperation = TableOperation.Insert(empHistory);
                table.Execute(insertOperation);
            }
        }
    }
    catch (Exception ex)
    {
        //var details = new System.IO.StreamReader(((Microsoft.WindowsAzure.Storage.StorageException)ex)..Response.GetResponseStream()).ReadToEnd();
        LogFile.Error("EmployeeOnlineHistory.setStatus",ex);
    }
}
Dan Homola
  • 3,819
  • 1
  • 28
  • 43
Ryan
  • 5,456
  • 25
  • 71
  • 129
  • That picture doesn't really help, aside from confirming error 400. Would "would" help is to show the code you executed which resulted in the bad request: how you set up the storage client, how you set up the table, then went to insert, etc. – David Makogon Feb 13 '13 at 20:44
  • I copy-pasted the code. Hope this helps – Ryan Feb 13 '13 at 22:08
  • 1
    It would help if you said which of the several cases is failing. Also, you're apparently setting some properties outside of this code (eg, PartitionKey and RowKey) so it would help to know what those are and what they're being set to. – Brian Reischl Feb 13 '13 at 22:51
  • I noticed that when the Exception is thrown first, there is no "View Detail" option but when you continue debugging and the flow goes back to the caller (where the exception pops up again), you can see the View Detail option. From there you can use @Juha Palomäki 's answer to find the error – S Raghav Apr 23 '17 at 07:07

22 Answers22

180

400 Error means there's something wrong with the value of one of your properties. One way to find out is to trace the request/response through Fiddler and see the actual data being sent to Windows Azure Storage.

Taking a wild guess, I'm assuming by taking a quick glance at your code that in your model you have some Date/Time type properties (OfflineTimestamp, OnlineTimestamp) and observed that in certain scenarios one of them is initialized with the default value which is "DateTime.MinValue". Please note that the minimum value allowed for a Date/Time type attribute is Jan 1, 1601 (UTC) in Windows Azure[http://msdn.microsoft.com/en-us/library/windowsazure/dd179338.aspx]. Please see if that's not the case. If that's the case, then you could make them nullable type fields so that they don't get populated with the default values.

Have a look at Juha Palomäki's answer below as well... there sometimes is a slightly more useful message in the exception where he suggests (RequestInformation.ExtendedErrorInformation.ErrorMessage)

GPR
  • 492
  • 5
  • 11
Gaurav Mantri
  • 128,066
  • 12
  • 206
  • 241
  • 296
    For the love of God, if someone from the Azure team reads this, please make the SDK return more information than the 400 Bad Request error. I have no idea why the DateTime in table storage can't have the same minimum date as the .NET DateTime object, but I wasted a good day on this one. By the time I got down to which property caused the problem, I happened across this as well, which helped. Now, before I ever insert/update a model with a DateTime for table storage, I have to run checks on all DateTime properties. NOT ideal... – Michael Oct 16 '13 at 17:18
  • 8
    While we're at it, you can't have an enum property as well. I had to convert property to Integer – Martin Jan 09 '14 at 11:36
  • That's true. Table storage currently supports primitive data types only. There's a 3rd party library - Lucifure Stash (http://lucifurestash.codeplex.com/) which has a support for other data types as well. – Gaurav Mantri Jan 09 '14 at 13:21
  • 1
    In my case I was not setting RowKey. Why on earth RowKey is not initialized as empty string I will never know. I hate to think how many hours I lost on this. At least 6. – Tim Murphy Jul 10 '14 at 08:47
  • Gaurav I am getting same error but only when upload parallel http://stackoverflow.com/questions/24229288/parallel-blob-upload-throwing-404-bad-request-intermittently – Imran Qadir Baksh - Baloch Aug 18 '14 at 11:48
  • 20
    Apparently, table names cannot have hyphens as well. Took me an hour to figure that out. – Amogh Natu Oct 13 '15 at 14:35
  • 5
    Table names cannot have underscores either.. that's why I'm here – Quango Dec 23 '15 at 12:12
  • 2
    I imagine RowKey is not initialised with empty string as this is the main lookup value and only indexed column... it's to remind you to populate it I would have thought.... this is only my guess though... As far as table names go.. have a read of this... https://blogs.msdn.microsoft.com/jmstall/2014/06/12/azure-storage-naming-rules/ – dreadeddev Apr 04 '16 at 10:34
  • The "Oops it failed, have a nice day" error message. How informative! – garryp May 16 '16 at 14:21
  • 1
    In my case it was a mismatch between the Azure Storage library and the Storage Emulator versions. – Jose Parra Sep 05 '16 at 06:37
  • Quango, I fell into this as well because my table name had an underscore. – jpierson Feb 21 '17 at 20:44
  • I just upgraded Azure Storage NuGet lib and started to get 400 error. The "interesting" point is, that when I tried to install newer Azure SDK version, it shown the same version I have already, bu when I tried to install a stand-alone Storage Version - only then I saw that newer version available... – Illidan Jul 15 '17 at 04:59
  • Also, you cannot use column names such as "Id", "$pk", "$id", "_rid", "_self", "_etag", "_attachments", "_ts" when using the Table Endpoint of the current CosmosDB Emulator even though Microsoft claims that it is plug compatible. It's not. We were using column name "Id" successfully with classic Azure Table Storage as well as with the old Azure Storage Emulator. This appears to be a change with CosmosDB's table endpoint. – Manfred Nov 22 '19 at 21:16
  • It can also be missing or bad access key – brianc Jun 16 '20 at 00:50
  • Thanks for the answer. Changed my "DateTime" properties to "DateTime?" and it worked! :D – Creative Sep 03 '20 at 12:56
  • In my case, it was having `#` in the partition key value – Pejman Nikram Nov 10 '22 at 17:43
151

The StorageException contains also a little bit more detailed information about error.

Check in debugger: StorageException.RequestInformation.ExtendedInformation

enter image description here

Juha Palomäki
  • 26,385
  • 2
  • 38
  • 43
  • 10
    Why is this information not a the top level exception? – Wilko van der Veen Jul 07 '17 at 07:02
  • For me this highlighted .. "Append blob not supported by emulator" .. FML – Michiel Cornille Sep 03 '18 at 11:42
  • `The specifed resource name contains invalid characters.` my table name had dashes in it... just like my queue names...sigh. Hopefully searching picks this up for more people! see: https://stackoverflow.com/questions/45305556/azure-table-storage-names-invalid-characters – Nateous May 18 '20 at 11:38
  • I had similar problem with table name. Appears in Table Storage a dash is not allowed but in Cosmos DB it is. – bytedev Aug 28 '20 at 03:28
62

In my case it was a forward slash in the RowKey.

I also received an 'OutOfRangeInput - One of the request inputs is out of range.' error when trying to add manually through the storage emulator.

Characters Disallowed in Key Fields

The following characters are not allowed in values for the PartitionKey and RowKey properties:

  • The forward slash (/) character
  • The backslash (\) character
  • The number sign (#) character
  • The question mark (?) character
  • Control characters from U+0000 to U+001F, including:
    • The horizontal tab (\t) character
    • The linefeed (\n) character
    • The carriage return (\r) character
    • Control characters from U+007F to U+009F

http://msdn.microsoft.com/en-us/library/dd179338.aspx

I wrote an extension method to handle this for me.

public static string ToAzureKeyString(this string str)
{
    var sb = new StringBuilder();
    foreach (var c in str
        .Where(c => c != '/'
                    && c != '\\'
                    && c != '#'
                    && c != '/'
                    && c != '?'
                    && !char.IsControl(c)))
        sb.Append(c);
    return sb.ToString();
}
Shawn McGough
  • 1,980
  • 2
  • 22
  • 32
  • 4
    This was my issue too. Your extension method works like a champ! – James Wilson Dec 17 '14 at 02:14
  • 1
    I loved the Extension Method. Saved me. – Newton Sheikh Mar 04 '16 at 11:01
  • Alternate response given here which does a regex replace http://stackoverflow.com/a/28788382/285795 – ΩmegaMan May 17 '16 at 19:27
  • Fixed it for me. I had a forward slash. Seemed like a good character for a pseudo compound key. – richard Oct 22 '16 at 00:49
  • 1
    This extension method is not removing several characers that are not allowed. Eg: space, "(", ")" ... https://learn.microsoft.com/en-us/rest/api/storageservices/Understanding-the-Table-Service-Data-Model?redirectedfrom=MSDN – Tiago Andrade e Silva Jan 19 '18 at 17:00
  • I was getting an "Invalid Query Syntax" message. Changing RowKey value from `DateTime.UtcNow.ToString()` to `DateTime.UtcNow.ToString(dd-MM-yyyy)` solved the issue. – Hari Aug 16 '23 at 05:14
7

I faced the same issue but the reason in my case was due to size. After digging into the additional exception properties (RequestInformation.ExtendedErrorInformation), found the reason:

ErrorCode : PropertyValueTooLarge ErrorMessage: The property value exceeds the maximum allowed size (64KB). If the property value is a string, it is UTF-16 encoded and the maximum number of characters should be 32K or less.

Nibras Manna
  • 71
  • 1
  • 3
5

well, in my case i was trying to do this:

CloudBlobContainer container = blobClient.GetContainerReference("SessionMaterials");
await container.CreateIfNotExistsAsync();

because of ContainerName SessionMaterials (as a habit writing in Pascal Case and Camel Case :D) it was causing 400 bad request. So, I just have to make it sessionmaterials. and it worked.

Hope this helps some one.

PS:- Just check exception http response or use fiddler to capture request and response.

Jawand Singh
  • 1,929
  • 1
  • 24
  • 21
3

Sometimes it's because your partitionKey or rowKey is NULL

(it was the case for me)

demo
  • 6,038
  • 19
  • 75
  • 149
Maroine Abdellah
  • 576
  • 1
  • 5
  • 21
3

in my case : Container name was in capital letter. there are limitations when using chars. enter image description here

Ravi Anand
  • 5,106
  • 9
  • 47
  • 77
1

A documentation from MS about all the Table Service Error Codes can be found here

huha
  • 4,053
  • 2
  • 29
  • 47
1

I was getting a (400) Bad Request, StatusMessage:Bad Request, ErrorCode:OutOfRangeInput when the entity had a property DateTime not set (= DateTime.MinValue)

Stig
  • 1,974
  • 2
  • 23
  • 50
1

I had the same BadRequest(400) Error, at the end I fill manually :

enter image description here

And worked for me. Hope this helps!

gatsby
  • 1,148
  • 11
  • 12
  • This answer is correct. I wasted about an hour and it tuns out that even `Timestamp` must be generated manually. It's really annoying. – Roman Koliada Jul 07 '18 at 22:51
0

I also faced same kind of issue. In my case PartitionKey value was not set, so by default PartitionKey value was null, which resulted in Object reference not set to an instance of an object. exception

Check if you are providing the appropriate values for PartitionKey or RowKey, you may face such problem.

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
Dilip Nannaware
  • 1,410
  • 1
  • 16
  • 24
0

I fixed my cases and it worked fine

My cases:

  1. Row key is not in correct format (400).
  2. Combination of partitionkey and rowkey is not unique (409).
Kurkula
  • 6,386
  • 27
  • 127
  • 202
0

I was getting a 400 Bad Request because I was using ZRS (Zone Redundant Storage), and Analytics isn't available for this type of storage. I wasn't aware I was using Analytics.

I deleted the storage container and recreated as GRS and now it works fine.

Aidan
  • 313
  • 1
  • 6
0

In my case: I included blob metadata with a tag name containing a hyphen.

var blob = container.GetBlockBlobReference(filename);
blob.Metadata.Add("added-by", Environment.UserName);
//.. other metadata
blob.UploadFromStream(filestream);

The dash in "added-by" was the problem, and later RTFM told me that tag names must conform to C# identifier conventions.

Ref: https://learn.microsoft.com/en-us/azure/storage/blobs/storage-properties-metadata

Underscore works fine.

Steve Friedl
  • 3,929
  • 1
  • 23
  • 30
0

In my case, i should not add PartitionKey and Rowkey in my entity class. It should be from the base class. Below would just work.

public class TableRunLogMessage:TableEntity
{
      public string status { get; set; }
      public long logged { get; set; }


      public TableRunLogMessage() { }
}
merry
  • 1
0

If you're using NodeJS and stumbled across this post, only to find that you don't get that lovely detailed information in your error object; you can utilize a proxy to get those details. However, since no one here mentions HOW to use a proxy.

The simplest way with NodeJS is by setting two environmental variables:

NODE_TLS_REJECT_UNAUTHORIZED=0
This disables SSL checks so you can intercept your own SSL requests. This leaves you open to Man-in-The-Middle attacks and should NEVER make it to production, and I wouldn't even leave it in development for long. However, it will allow you to intercept the HTTP Requests.

HTTP_PROXY=http://127.0.0.1:8888
This sets node to utilize a proxy listening on your localhost at port 8888. Port 8888 is the default for Fiddler. Many other proxies default to 8080.

If you're actually utilizing C#, like the author of this post is doing; you can simply install Fiddler and set it to intercept. By default it should intercept the requests. You may need to also trust Fiddler's certificate or otherwise do the equivalent of Node's "NODE_TLS_REJECT_UNAUTHORIZED=0".

Doug
  • 6,446
  • 9
  • 74
  • 107
0

I got 400-BadRequest response from Azure Storage Account Table API. Exception information showed that "The account being accessed does not support http.". I figured that we must use https in the connection string when "Secure transfer required" is enabled in storage account configuration as shown in the below image.enter image description here

Kalaiselvan
  • 119
  • 7
0

In my case for create new instalnce of "TableBotDataStore" class (MS bot framework) we pass "tableName" parameter with hyphen like "master-bot" and TableBotDataStore can have table names only with letters and numbers only

igor_bugaenko
  • 109
  • 1
  • 4
0

I had the same issue, the function was passing the containerNameKey as string. below is the code that gave error

container = blobClient.GetContainerReference(containerNameKey) 

I changed it to

container = blobClient.GetContainerReference(ConfigurationManager.AppSettings(containerNameKey).ToString()) 

It worked

Paul Roub
  • 36,322
  • 27
  • 84
  • 93
Vani
  • 1,345
  • 4
  • 27
  • 48
0

I got 400-BadRequest response when I tried to put too long value to the string field.

"A UTF-16-encoded value. String values may be up to 64 KiB in size. Note that the maximum number of characters supported is about 32 K or less."

https://learn.microsoft.com/en-us/rest/api/storageservices/understanding-the-table-service-data-model

  • This does not provide an answer to the question. You can [search for similar questions](https://stackoverflow.com/search), or refer to the related and linked questions on the right-hand side of the page to find an answer. If you have a related but different question, [ask a new question](https://stackoverflow.com/questions/ask), and include a link to this one to help provide context. See: [Ask questions, get answers, no distractions](https://stackoverflow.com/tour). – Bilal Dec 31 '20 at 11:42
0

For me I used table name with dash example: tablename: "table-1234", but tablename: "table1234" without dash worked.

Etnic
  • 76
  • 1
  • 6
0

For me, I tried to insert an entity into an Azure Storage Table with a PartitionKey/RowKey that included the "#" character. Annoying that this is disallowed, since it is common to use "#" as a separator in single-table design.

James Shapiro
  • 4,805
  • 3
  • 31
  • 46