Bug 21746 - Decimal.ToString FormatException "The specified format 'c' is invalid"
Summary: Decimal.ToString FormatException "The specified format 'c' is invalid"
Status: RESOLVED NOT_REPRODUCIBLE
Alias: None
Product: Android
Classification: Xamarin
Component: BCL Class Libraries ()
Version: 4.12.4
Hardware: Macintosh Mac OS
: Normal normal
Target Milestone: ---
Assignee: Marek Habersack
URL:
Depends on:
Blocks:
 
Reported: 2014-07-31 19:50 UTC by Steve Gordon
Modified: 2017-06-27 18:21 UTC (History)
4 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED NOT_REPRODUCIBLE

Description Steve Gordon 2014-07-31 19:50:33 UTC
After getting an update to our Android app out a little over a week ago, we started seeing an exception in Decimal.ToString(), even though we hadn't touched this code since our prior update. We did happen to upgrade our Xamarin Android version to 4.12.6 as part of this update.

We're seeing the following exception intermittently. We have not been able to reproduce the issue on our end:

java.lang.Throwable: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.FormatException: The specified format 'c' is invalid

 at System.NumberFormatter.NumberToString (System.String format, System.Globalization.NumberFormatInfo nfi) [0x00000] in :0
 at System.NumberFormatter.NumberToString (System.String format, Decimal value, IFormatProvider fp) [0x00000] in :0
 at System.Decimal.ToString (System.String format, IFormatProvider provider) [0x00000] in :0
 at Mobilligy.Models.DecimalExtensions.ToCurrencyUsd (Decimal d) [0x00000] in :0
 at Mobilligy.ViewModels.Main.NotificationViewModel.get_Amount () [0x00000] in :0
 at (wrapper delegate-invoke) :invoke_string__this___NotificationViewModel (Mobilligy.ViewModels.Main.NotificationViewModel)
 at System.Reflection.MonoProperty.GetterAdapterFrame[NotificationViewModel,String] (System.Reflection.Getter`2 getter, System.Object obj) [0x00000] in :0
 at System.Reflection.MonoProperty.GetValue (System.Object obj, System.Object[] index) [0x00000] in :0

Our code is as follows:

```
public static class DecimalExtensions
{
    private static NumberFormatInfo usdNumberFormat;

    static DecimalExtensions()
    {
        usdNumberFormat = new NumberFormatInfo
        {
            CurrencyDecimalDigits = 2,
            CurrencyDecimalSeparator = ".",
            CurrencyGroupSeparator = ",",
            CurrencyGroupSizes = new [] { 3 },
            CurrencySymbol = "$",
            CurrencyNegativePattern = 1,
        };
    }

    public static string ToCurrencyUsd(this decimal d)
    {
        return d.ToString("c", usdNumberFormat);
    }
}

```
Comment 1 Udham Singh 2014-08-01 05:53:27 UTC
We have tried to reproduce this issue but not able to reproduce this. To reproduce this issue we have followed the steps mentioned below : 

1. Create a simple android application and implemented the code provided in bug description.
2. Run and debug the application.

Screencast : http://screencast.com/t/0jpaDP1i

As user has mentioned in bug description that this exception is intermittent and user has not been able to reproduce this issue on his/her end right now and we are also not getting this issue at our end.

We may have to see if a developer can figure out what's going on from the stack trace provided in bug description.

Environment Info :

=== Xamarin Studio ===

Version 5.3 (build 362)
Installation UUID: 011d70a5-dede-428b-ab04-ef451c2e539d
Runtime:
	Mono 3.4.0 ((no/954ed3c)
	GTK+ 2.24.23 (Raleigh theme)

	Package version: 304000214

=== Apple Developer Tools ===

Xcode 5.1 (5084)
Build 5B130a

=== Xamarin.Mac ===

Version: 1.10.0.4 (Enterprise Edition)

=== Xamarin.iOS ===

Version: 7.2.6.26 (Enterprise Edition)
Hash: f10e5ed
Branch: 
Build date: 2014-07-23 11:06:08-0400

=== Xamarin.Android ===

Version: 4.12.6 (Enterprise Edition)
Android SDK: /Users/MM/Desktop/android-sdk-macosx
	Supported Android versions:
		2.1   (API level 7)
		2.2   (API level 8)
		2.3   (API level 10)
		3.1   (API level 12)
		3.2   (API level 13)
		4.0   (API level 14)
		4.0.3 (API level 15)
		4.1   (API level 16)
		4.2   (API level 17)
		4.3   (API level 18)
		4.4   (API level 19)
Java SDK: /usr
java version "1.6.0_65"
Java(TM) SE Runtime Environment (build 1.6.0_65-b14-462-11M4609)
Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-462, mixed mode)

=== Build Information ===

Release ID: 503000362
Git revision: 7881c2a09973b95c125f71bae11e84c2fc6cba87
Build date: 2014-07-30 03:50:59-04
Xamarin addins: 022da9c75aae7909a36d0323382ca002b6e59eed

=== Operating System ===

Mac OS X 10.9.2
Darwin MacMini.local 13.1.0 Darwin Kernel Version 13.1.0
    Thu Jan 16 19:40:37 PST 2014
    root:xnu-2422.90.20~2/RELEASE_X86_64 x86_64
Comment 2 Steve Gordon 2014-08-01 14:48:59 UTC
We are only seeing this in the wild.

If you have any ideas around what could be causing it, we can modify the code to help diagnose the problem.

This could include having a "more reliable" fall back method that we can invoke if we hit this situation, or possibly additional logging.

This is our highest volume crash that we're seeing.
Comment 3 Marek Habersack 2014-08-01 16:21:25 UTC
Looking at the NumberFormatter code about the *only* cause might be "c" vs "C" in the format. The formatter will throw this particular exception only if the format specifier is unrecognized, which is the case with "c". I can't imagine why it would work sometimes and break other times, but that's about the only reason I can currently think of. 

I'm trying to repro the issue locally, will update the bug with more info as soon as I have something to report
Comment 4 Steve Gordon 2014-08-05 15:38:28 UTC
Unfortunately, switching to "C" hasn't helped. We published an update that uses "C" and we're still seeing the exception:

java.lang.Throwable: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.FormatException: The specified format 'C' is invalid
  at System.NumberFormatter.NumberToString (System.String format, System.Globalization.NumberFormatInfo nfi) [0x00000] in <filename unknown>:0 
  at System.NumberFormatter.NumberToString (System.String format, Decimal value, IFormatProvider fp) [0x00000] in <filename unknown>:0 
  at System.Decimal.ToString (System.String format, IFormatProvider provider) [0x00000] in <filename unknown>:0 
  at Mobilligy.Models.DecimalExtensions.ToCurrencyUsd (Decimal d) [0x00000] in <filename unknown>:0
Comment 5 Christophe Oosterlynck 2014-08-11 09:32:18 UTC
I'm having a similar issue:

Android app crashes once in a while when calling Decimal.ToString(). However, I'm not using 'c' as format but 'N2'.

Maybe it is something threading related as we call this method also from threads other than the main thread.

If it occurs again in the near future I will post a stack trace here.

Our code is as follows:

static class Extensions
{
    internal static string ToDefaultAmountString(this decimal amount)
    {
        return amount.ToString(Constants.DefaultAmountFormat);
    }
}

static class Constants
{
    public const string DefaultAmountFormat = "N2";
}
Comment 6 Steve Gordon 2014-08-19 12:33:35 UTC
Any chance that this can be prioritized? As I mentioned, this is the single largest crash that we're seeing.

At a minimum, if you can perhaps identify how we might be able to work around it, that would be great. We can roll our own decimal to currency implementation if needed, but it's unclear how far we need to go. (i.e.: can we safely rely on Decimal.ToString() with the default formatting?)

Any help would be greatly appreciated. Thanks!
Comment 7 Marek Habersack 2014-08-20 09:18:29 UTC
Unfortunately, I can't promise to be able to prioritize this issue right now :( Especially that I've failed to reproduce this problem locally. @Christophe, it might indeed be a threading issue with the formatter classes. It would be great if we had a simple repro for this. Perhaps you can indentify the threading patterns in your applications as related to this and replicate them in a simple test case?
Comment 8 Steve Gordon 2014-08-20 15:49:34 UTC
In our case, our extension method is only used for UI purposes and we only do the string formatting on the UI thread. :-/
Comment 9 Marek Habersack 2014-08-25 06:12:09 UTC
@Steve, @Christophe - do your applications support l10n by chance? And, for the crashes you see, do you have any information on the device locale at the time of the crash?
Comment 10 Christophe Oosterlynck 2014-08-25 07:22:17 UTC
I didn't have this issue anymore since my comment here. But I'm not working much with that part of our code at the moment. I'll probably return to that piece of code within a few weeks. Maybe I'll have a scenario then which allows to reproduce the crash.

Our app is forced to use nl-BE. To expand my previous code:

static class Extensions
{
    internal static string ToDefaultAmountString(this decimal amount)
    {
        return amount.ToString(Constants.DefaultAmountFormat, Constants.BelgiumCulture);
    }
}

static class Constants
{
    public const string DefaultAmountFormat = "N2";

    public static CultureInfo BelgiumCulture { get { return belgiumCulture ?? (belgiumCulture = new CultureInfo("nl-BE")); } }

        [ThreadStatic] private static CultureInfo belgiumCulture;
}
Comment 11 Marek Habersack 2014-12-10 08:11:32 UTC
We are going to need a self-contained, reliable repro for this issue to fix it. I'm unable to reproduce it and eyballing the code doesn't reveal anything which might cause the problem.
Comment 12 Christophe Oosterlynck 2014-12-10 08:16:00 UTC
Since my last comment, I haven't been able to reproduce this anymore. I never had a reproducible scenario but I used to encounter this bug from time to time, but not anymore.

Maybe a recent Xamarin update has resolved this issue or maybe changes in our code fixed it.
Comment 13 Marek Habersack 2014-12-10 08:27:30 UTC
That's good news I guess, although we don't know what fixed (or "fixed") it. I'm going to leave this bug as NEEDINFO for a while more, perhaps somebody will come up with a repro. Thanks!
Comment 14 Chris Hardy [MSFT] 2017-06-27 18:21:48 UTC
Unfortunately, we’re unable to reproduce this report. If this issue is still occurring for you, please reopen this issue and attach a reproduction to the bug by starting with a clean Xamarin.Android project adding just the code necessary to demonstrate the issue.