# Cannot cast from \[java.lang.String\] to \[char\] error

**URL:** <https://discuss.elastic.co/t/cannot-cast-from-java-lang-string-to-char-error/380243>\
**Category:** Elastic Search\
**Tags:** painless\
**Created:** [July 18, 2025, 3:22am UTC](https://discuss.elastic.co/t/cannot-cast-from-java-lang-string-to-char-error/380243 "2025-07-18T03:22:47Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Simriti\_Bundhoo](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/simriti_bundhoo/32/144148_2.png) [@Simriti\_Bundhoo](https://discuss.elastic.co/u/Simriti_Bundhoo)\
**Post date:** [July 18, 2025, 3:22am UTC](https://discuss.elastic.co/t/cannot-cast-from-java-lang-string-to-char-error/380243/1 "2025-07-18T03:22:47Z")

</div>

Hello, I am currently learning painless and one of the exercises is to associate letter grades to a range of numbers. I have been stuck on a specific error which is:

```auto
{
  "error": {
    "root_cause": [
      {
        "type": "script_exception",
        "reason": "compile error",
        "script_stack": [
          """... {
			    letter_grade = 'A';
			  } 
			  else ...""",
          " ^---- HERE"
        ],
        "script": """
			Map toLetterGrade(int numeric_grade){
			  Map grade = new HashMap();
			  char letter_grade;
			  if (numeric_grade >= 93 && numeric_grade <= 100) {
			    letter_grade = 'A';
			  } 
			  else if (numeric_grade >= 85 && numeric_grade <= 92) {
			    letter_grade = 'B';
			  } 
			  else if (numeric_grade >= 76 && numeric_grade <= 84) {
			    letter_grade = 'C';
			  } 
			  else if (numeric_grade >= 65 && numeric_grade <= 75) {
			    letter_grade = 'D';
			  } 
			  else if (numeric_grade >= 0 && numeric_grade <= 64) {
			    letter_grade = 'F';
			  } 
			  else {
			    throw new IllegalArgumentException();
			  }
			  grade.put(letter_grade, numeric_grade);
			  return grade;
			}
			return toLetterGrade(params.numeric_grade);
		""",
        "lang": "painless",
        "position": {
          "offset": 181,
          "start": 156,
          "end": 206
        }
      }
    ],
    "type": "script_exception",
    "reason": "compile error",
    "script_stack": [
      """... {
			    letter_grade = 'A';
			  } 
			  else ...""",
      " ^---- HERE"
    ],
    "script": """
			Map toLetterGrade(int numeric_grade){
			  Map grade = new HashMap();
			  char letter_grade;
			  if (numeric_grade >= 93 && numeric_grade <= 100) {
			    letter_grade = 'A';
			  } 
			  else if (numeric_grade >= 85 && numeric_grade <= 92) {
			    letter_grade = 'B';
			  } 
			  else if (numeric_grade >= 76 && numeric_grade <= 84) {
			    letter_grade = 'C';
			  } 
			  else if (numeric_grade >= 65 && numeric_grade <= 75) {
			    letter_grade = 'D';
			  } 
			  else if (numeric_grade >= 0 && numeric_grade <= 64) {
			    letter_grade = 'F';
			  } 
			  else {
			    throw new IllegalArgumentException();
			  }
			  grade.put(letter_grade, numeric_grade);
			  return grade;
			}
			return toLetterGrade(params.numeric_grade);
		""",
    "lang": "painless",
    "position": {
      "offset": 181,
      "start": 156,
      "end": 206
    },
    "caused_by": {
      "type": "class_cast_exception",
      "reason": "Cannot cast from [java.lang.String] to [char]."
    }
  },
  "status": 400
}

```

For reference, my current code is:

```auto
POST _scripts/painless/_execute
{
	"script": {
		"lang": "painless",
		"source": """
			Map toLetterGrade(int numeric_grade){
			  Map grade = new HashMap();
			  char letter_grade;
			  if (numeric_grade >= 93 && numeric_grade <= 100) {
			    letter_grade = 'A';
			  } 
			  else if (numeric_grade >= 85 && numeric_grade <= 92) {
			    letter_grade = 'B';
			  } 
			  else if (numeric_grade >= 76 && numeric_grade <= 84) {
			    letter_grade = 'C';
			  } 
			  else if (numeric_grade >= 65 && numeric_grade <= 75) {
			    letter_grade = 'D';
			  } 
			  else if (numeric_grade >= 0 && numeric_grade <= 64) {
			    letter_grade = 'F';
			  } 
			  else {
			    throw new IllegalArgumentException();
			  }
			  grade.put(letter_grade, numeric_grade);
			  return grade;
			}
			return toLetterGrade(params.numeric_grade);
		""",
		"params": {
      "numeric_grade": 98
		}
	}
}	

```

I cannot understand what is causing the error and how to fix it, so any help/fix is appreciated! (FYI: the code does run if I change the data type to String, I am just curious why char is not working here 🤔)

---

<div class="post-metadata">

**Author:** ![Tortoise](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/tortoise/32/147587_2.png) [@Tortoise](https://discuss.elastic.co/u/Tortoise)\
**Post date:** [July 18, 2025, 4:11am UTC](https://discuss.elastic.co/t/cannot-cast-from-java-lang-string-to-char-error/380243/2 "2025-07-18T04:11:11Z")

</div>

Hello @Simriti_Bundhoo

This is what i found : Even though `'A'` looks like a Java `char`, Painless interprets it as a `String`.

```auto
POST _scripts/painless/_execute
{
  "script": {
    "lang": "painless",
    "source": """
      Map toLetterGrade(int numeric_grade){
        Map grade = new HashMap();
        char letter_grade;
        if (numeric_grade >= 93 && numeric_grade <= 100) {
          letter_grade = "A".charAt(0);
        } 
        else if (numeric_grade >= 85 && numeric_grade <= 92) {
          letter_grade = "B".charAt(0);
        } 
        else if (numeric_grade >= 76 && numeric_grade <= 84) {
          letter_grade = "C".charAt(0);
        } 
        else if (numeric_grade >= 65 && numeric_grade <= 75) {
          letter_grade = "D".charAt(0);
        } 
        else if (numeric_grade >= 0 && numeric_grade <= 64) {
          letter_grade = "F".charAt(0);
        } 
        else {
          throw new IllegalArgumentException();
        }
        grade.put(Character.toString(letter_grade), numeric_grade);
        return grade;
      }
      return toLetterGrade(params.numeric_grade);
    """,
    "params": {
      "numeric_grade": 98
    }
  }
}

```

> **[Types | Reference](https://www.elastic.co/docs/reference/scripting-languages/painless/painless-types)**
>
> A type is a classification of data used to define the properties of a value. These properties specify what data a value represents and the rules for how...

Thanks!!

---

<div class="post-metadata">

**Author:** ![Simriti\_Bundhoo](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/simriti_bundhoo/32/144148_2.png) [@Simriti\_Bundhoo](https://discuss.elastic.co/u/Simriti_Bundhoo)\
**Post date:** [July 18, 2025, 5:18am UTC](https://discuss.elastic.co/t/cannot-cast-from-java-lang-string-to-char-error/380243/3 "2025-07-18T05:18:43Z")

</div>

@Tortoise, Hey, is that the right link you meant to send? Because the documentation clearly says `char` is a primitive type, so I assume it’s a valid type and should work as expected. I don't see it mentioning anywhere that Painless interprets a single character as `String` despite it being declared as a `char` type.

---

<div class="post-metadata">

**Author:** ![RainTown](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/raintown/32/140206_2.png) [@RainTown](https://discuss.elastic.co/u/RainTown)\
**Post date:** [July 18, 2025, 11:40am UTC](https://discuss.elastic.co/t/cannot-cast-from-java-lang-string-to-char-error/380243/4 "2025-07-18T11:40:35Z")

</div>

Turning question around, where in the documentation does it say `"AA"` is a string but `"A"` is a char ? Rather it gives an explicit example to cast a one-char-long-string into a char.

```auto
String s = "s";
char c = (char)s;

```

This cut and paste directly from the painless documentation.

My version of your code, HTH!

```auto
POST _scripts/painless/_execute
{
  "script": {
    "lang": "painless",
    "source": """
      Map toLetterGrade(int numeric_grade){
        Map grade = new HashMap();
        char letter_grade;
        char myA=(char)"A";char myB=(char)"B";char myC=(char)"C";char myD=(char)"D";char myF=(char)"F";
        if (numeric_grade >= 93 && numeric_grade <= 100) {
          letter_grade = myA;
        } 
        else if (numeric_grade >= 85 && numeric_grade <= 92) {
          letter_grade = myB;
        } 
        else if (numeric_grade >= 76 && numeric_grade <= 84) {
          letter_grade = myC;
        } 
        else if (numeric_grade >= 65 && numeric_grade <= 75) {
          letter_grade = myD;
        } 
        else if (numeric_grade >= 0 && numeric_grade <= 64) {
          letter_grade = myF;
        } 
        else {
          throw new IllegalArgumentException();
        }
        grade.put(Character.toString(letter_grade), numeric_grade);
        return grade;
      }
      return toLetterGrade(params.numeric_grade);
    """,
    "params": {
      "numeric_grade": 99
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![Simriti\_Bundhoo](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/simriti_bundhoo/32/144148_2.png) [@Simriti\_Bundhoo](https://discuss.elastic.co/u/Simriti_Bundhoo)\
**Post date:** [July 21, 2025, 7:11am UTC](https://discuss.elastic.co/t/cannot-cast-from-java-lang-string-to-char-error/380243/5 "2025-07-21T07:11:14Z")

</div>

Hi @RainTown,

Thanks for the response and example, appreciate it.

Yeah, you're right, the docs don't say "AA" should be a char. I just assumed that since I was using single quotes and only one character, the compiler would interpret it as a char. It feels redundant that even when the variable is clearly declared as a char, you still have to cast a one-character string to it. Haven’t really seen this kind of strictness in other languages I’ve worked with, so I was just curious why it behaves that way here. So yeah, your example works, but it still doesn’t fully answer why it has to be that way in Painless.
