diff --git a/CHANGELOG.md b/CHANGELOG.md
index 00d2d7309442f1d3e9be2959c1f493d56e893461..73433a48ceb379ffc792b86613ecdbf158793727 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -33,6 +33,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Fixed ###
 - [#203](https://gitlab.com/caosdb/caosdb-server/-/issues/203)
 
+* Searching for values in scientific notation
+  [#143](https://gitlab.com/caosdb/caosdb-server/-/issues/143)
 * Denying a role permission has no effect
   [#196](https://gitlab.com/caosdb/caosdb-server/-/issues/196). See security
   notes below.
diff --git a/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java b/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java
index 352a7428f2007fc59cbf0b3fb7f067d1198857c1..5c9f4c2ca13f8481d075117cb34dec41e5aeeab8 100644
--- a/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java
+++ b/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java
@@ -46,7 +46,7 @@ public class ExecuteQuery extends FlagJob {
       try {
         queryInstance.execute(getTransaction().getAccess());
       } catch (final ParsingException e) {
-        getContainer().addError(ServerMessages.QUERY_PARSING_ERROR);
+        getContainer().addError(ServerMessages.QUERY_PARSING_ERROR(e.getMessage()));
       } catch (final UnsupportedOperationException e) {
         getContainer().addError(ServerMessages.QUERY_EXCEPTION);
         getContainer()
diff --git a/src/main/java/org/caosdb/server/query/CQLLexer.g4 b/src/main/java/org/caosdb/server/query/CQLLexer.g4
index 518d1628b16ab9d0d66816b88e9b9115b765b6d4..be6dcfa99d2f9c48cba8a0f7fccb7f97b277e01d 100644
--- a/src/main/java/org/caosdb/server/query/CQLLexer.g4
+++ b/src/main/java/org/caosdb/server/query/CQLLexer.g4
@@ -522,31 +522,55 @@ TODAY:
     [Tt][Oo][Dd][Aa][Yy] WHITE_SPACE_f?
 ;
 
+/** */
+COLON:
+    ':'
+;
+
+/** Matches signed and unsigned numbers with decimal points, also numbers in scientific notation. */
+DECIMAL_NUMBER:
+    ((HYPHEN_f | PLUS ) WHITE_SPACE_f?)? 
+    ( NUM_f? DOT NUM_f WHITE_SPACE_f? E_NOTATION_f?
+    | NUM_f WHITE_SPACE_f? E_NOTATION_f
+    )
+;
+
 /** */
 HYPHEN:
-    '-'
+    HYPHEN_f
 ;
 
 /** */
-COLON:
-    ':'
+PLUS:
+	'+'
 ;
 
 /** */
-NUM:
+fragment
+HYPHEN_f:
+	'-'
+;
+
+/** Matches only unsigned integer numbers. */
+UNSIGNED_INT:
     NUM_f
-    | DOT NUM_f
-    | NUM_f DOT NUM_f
 ;
 
 /** */
+fragment
 NUM_f:
     ('0'..'9')+
 ;
 
+/** */
+fragment
+E_NOTATION_f:
+	[Ee] WHITE_SPACE_f? [+-]? WHITE_SPACE_f? NUM_f
+;
+
 /** */
 TXT:
-    ('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '-' {_input.LA(1) != '>'}? | '+' | '&' | ';' | ',' | '$' | ':' | '%' | '^' | '~' {_input.LA(1) != '='}? | '`' | '´' | 'ö' | 'ä' | 'ß' | 'ü' | 'Ö' | 'Ä' | 'Ü' | '@' | '[' | ']' | '{' | '}' )+
+    ('a'..'z' | 'A'..'Z' | NUM_f | '_' | '-' {_input.LA(1) != '>'}? | PLUS | '&' | ';' | ',' | '$' | ':' | '%' | '^' | '~' {_input.LA(1) != '='}? | '`' | '´' | 'ö' | 'ä' | 'ß' | 'ü' | 'Ö' | 'Ä' | 'Ü' | '@' | '[' | ']' | '{' | '}' )+
 ;
 
 /** */
diff --git a/src/main/java/org/caosdb/server/query/CQLParser.g4 b/src/main/java/org/caosdb/server/query/CQLParser.g4
index d5e375102d79d395b1f06c62c5aef9537092b0fc..8615bae31fae67eb0bd3315f664bfa708db61618 100644
--- a/src/main/java/org/caosdb/server/query/CQLParser.g4
+++ b/src/main/java/org/caosdb/server/query/CQLParser.g4
@@ -282,20 +282,20 @@ transaction_time returns [String tqp, String op]
  */
 datetime
 :
-    NUM // year
+    UNSIGNED_INT // year
     (
-        HYPHEN NUM // mon
+        HYPHEN UNSIGNED_INT // mon
         (
-            HYPHEN NUM // day of mon
+            HYPHEN UNSIGNED_INT // day of mon
             (
                 (m=TXT {$m.text.equals("T")}?)?// compliance with iso datetime
-                NUM // hour
+                UNSIGNED_INT // hour
                 (
-                    COLON NUM // minut
+                    COLON UNSIGNED_INT // minut
                     (
-                        COLON NUM // sec
+                        COLON UNSIGNED_INT // sec
                         (
-                            DOT NUM // millisec
+                            DOT UNSIGNED_INT // millisec
                         )?
                     )?
                 )?
@@ -581,7 +581,7 @@ property returns [Query.Pattern pp, String agg]locals [StringBuffer sb]
         | like_pattern {$pp = $like_pattern.ep;}
         | ( double_quoted {$pp = $double_quoted.ep;} )
         | ( single_quoted {$pp = $single_quoted.ep;} )
-        | ((m=TXT | m=NUM | m=REGEXP_MARKER | m=ENTITY){$sb.append($m.text);})+  {$pp = new Query.Pattern($sb.toString(), Query.Pattern.TYPE_NORMAL);}
+        | ((m=TXT | m=UNSIGNED_INT | m=UNSIGNED_DECIMAL_NUMBER | m=REGEXP_MARKER | m=ENTITY){$sb.append($m.text);})+  {$pp = new Query.Pattern($sb.toString(), Query.Pattern.TYPE_NORMAL);}
     )
     WHITE_SPACE?
 ;
@@ -613,9 +613,8 @@ value returns [String str]
  */
 number_with_unit
 :
-    HYPHEN??
-    NUM
-    (WHITE_SPACE?? unit)?
+    ( UNSIGNED_INT | DECIMAL_NUMBER | ( HYPHEN | PLUS ) WHITE_SPACE? UNSIGNED_INT)
+    (WHITE_SPACE? unit)?
 ;
 
 /**
@@ -626,7 +625,7 @@ unit
     (~(WHITE_SPACE | WHICH | HAS_A | WITH_A | WHERE | DOT | AND | OR | RPAREN ))
     (~(WHITE_SPACE))*
     |
-    NUM SLASH (~(WHITE_SPACE))+
+    UNSIGNED_INT SLASH (~(WHITE_SPACE))+
 ;
 
 /**
diff --git a/src/main/java/org/caosdb/server/query/POV.java b/src/main/java/org/caosdb/server/query/POV.java
index 89ea9ad46e6205dfe0583e8f54551effd82a2658..0de160cdb6249ffaea10f4eeeafdf4884323a186 100644
--- a/src/main/java/org/caosdb/server/query/POV.java
+++ b/src/main/java/org/caosdb/server/query/POV.java
@@ -51,6 +51,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class POV implements EntityFilterInterface {
+  public static final Pattern NUMBER_PATTERN =
+      Pattern.compile(
+          "^((?:[+-]\\s*)?[0-9]+(?:\\.[0-9]+)?(?:\\s*[eE]\\s*[+-]?\\s*[0-9]+)?)\\s*([^-]*)$");
   private SubProperty subp = null;
   public static int retry = 10;
   private int retry_count = 0;
@@ -116,14 +119,22 @@ public class POV implements EntityFilterInterface {
 
       // try and parse as integer
       try {
-        final Pattern dp = Pattern.compile("^(-?[0-9]++)\\s*([^(\\.[0-9])-][^-]*)?$");
-        final Matcher m = dp.matcher(value);
+        final Matcher m = NUMBER_PATTERN.matcher(this.value);
         if (!m.matches()) {
           throw new NumberFormatException();
         }
         final String vIntStr = m.group(1);
+        this.vInt = Integer.parseInt(vIntStr.replaceAll("\\s", ""));
+        if (vIntStr.matches(".*\\s.*")) {
+          // empty space in scientific notation is a common typo
+          throw new Query.ParsingException(
+              "You typed \""
+                  + vIntStr
+                  + "\". Empty spaces are not allowed in numbers. Did you mean \""
+                  + vIntStr.replaceAll("\\s", "")
+                  + "\"?");
+        }
         this.unitStr = m.group(2);
-        this.vInt = Integer.parseInt(vIntStr);
       } catch (final NumberFormatException e) {
         this.vInt = null;
       }
@@ -132,15 +143,23 @@ public class POV implements EntityFilterInterface {
       if (this.vInt == null) {
         try {
           // Doubles are allowed without dots, for example when the integer overflows.
-          final Pattern dp = Pattern.compile("^(-?[0-9]+(?:\\.)?(?:[0-9]+))\\s*([^-]*)$");
-          final Matcher m = dp.matcher(value);
+          final Matcher m = NUMBER_PATTERN.matcher(this.value);
           if (!m.matches()) {
             throw new NumberFormatException();
           }
           final String vDoubleStr = m.group(1);
-          this.unitStr = m.group(2);
 
-          this.vDouble = Double.parseDouble(vDoubleStr);
+          this.vDouble = Double.parseDouble(vDoubleStr.replaceAll("\\s", ""));
+          if (vDoubleStr.matches(".*\\s.*")) {
+            // empty space in scientific notation is a common typo
+            throw new Query.ParsingException(
+                "You typed \""
+                    + vDoubleStr
+                    + "\". Empty spaces are not allowed in numbers. Did you mean \""
+                    + vDoubleStr.replaceAll("\\s", "")
+                    + "\"?");
+          }
+          this.unitStr = m.group(2);
         } catch (final NumberFormatException e) {
           this.vDouble = null;
         }
@@ -153,7 +172,7 @@ public class POV implements EntityFilterInterface {
           this.unit = getUnit(this.unitStr);
         } catch (final ParserException e) {
           e.printStackTrace();
-          throw new UnsupportedOperationException("Could not parse the unit.");
+          throw new UnsupportedOperationException("Could not parse the unit:");
         }
 
         this.stdUnitSig = this.unit.normalize().getSignature();
diff --git a/src/main/java/org/caosdb/server/utils/ServerMessages.java b/src/main/java/org/caosdb/server/utils/ServerMessages.java
index 835087ce8825de6c136dabd746534bc42f3240d5..9e18ca9065ec407d2dfc795d173e8d97f11682be 100644
--- a/src/main/java/org/caosdb/server/utils/ServerMessages.java
+++ b/src/main/java/org/caosdb/server/utils/ServerMessages.java
@@ -617,4 +617,8 @@ public class ServerMessages {
     return new Message(
         MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "You cannot delete yourself.");
   }
+
+  public static Message QUERY_PARSING_ERROR(String message) {
+    return new Message(MessageType.Error, MessageCode.MESSAGE_CODE_QUERY_PARSING_ERROR, message);
+  }
 }
diff --git a/src/test/java/org/caosdb/server/query/POVTest.java b/src/test/java/org/caosdb/server/query/POVTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..7212423bbaf2ac4d3c5e33543d3e6ffe4e70b5e4
--- /dev/null
+++ b/src/test/java/org/caosdb/server/query/POVTest.java
@@ -0,0 +1,77 @@
+package org.caosdb.server.query;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.regex.Matcher;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+class POVTest {
+
+  public static final String MAX_INT = "2147483647";
+  public static final String MIN_INT = "-2147483648";
+  public static final String MAX_DOUBLE = "1.7976931348623157E308";
+  public static final String MIN_DOUBLE = "4.9E-324";
+
+  @ParameterizedTest
+  @ValueSource(strings = {"16", MAX_INT, MIN_INT, "0", "-0", "1", "- 1", "-1", "+1"})
+  void testNumberPatternMatchInteger(String intValue) {
+
+    Matcher matcher = POV.NUMBER_PATTERN.matcher(intValue);
+    assertTrue(matcher.matches());
+    assertEquals(intValue, matcher.group(1).toString());
+
+    Integer.valueOf(intValue.replaceAll("\\s", ""));
+
+    Matcher matcherWithUnit = POV.NUMBER_PATTERN.matcher(intValue + " m^2");
+    assertTrue(matcherWithUnit.matches());
+    assertEquals(intValue, matcherWithUnit.group(1).toString());
+    assertEquals("m^2", matcherWithUnit.group(2).toString());
+
+    Matcher matcherWithStrangeUnit = POV.NUMBER_PATTERN.matcher(intValue + " e");
+    assertTrue(matcherWithStrangeUnit.matches());
+    assertEquals(intValue, matcherWithStrangeUnit.group(1).toString());
+    assertEquals("e", matcherWithStrangeUnit.group(2).toString());
+  }
+
+  @ParameterizedTest
+  @ValueSource(
+      strings = {
+        "1.2123e+3",
+        "1.21234E+3",
+        "5.213e2",
+        "5.2234E2",
+        "16.0",
+        MAX_DOUBLE,
+        MIN_DOUBLE,
+        "0.0",
+        "-0.0",
+        "1.2",
+        "- 1.2",
+        "-1.2",
+        "2e-323",
+        "2E-323",
+        "2E- 323",
+        "2 e -323",
+        "+ 2.2132e+23"
+      })
+  void testNumberPatternMatchDouble(String doubleValue) {
+
+    Matcher matcher = POV.NUMBER_PATTERN.matcher(doubleValue);
+    assertTrue(matcher.matches());
+    assertEquals(doubleValue, matcher.group(1).toString());
+
+    Double.valueOf(doubleValue.replaceAll("\\s", ""));
+
+    Matcher matcherWithUnit = POV.NUMBER_PATTERN.matcher(doubleValue + " m^2");
+    assertTrue(matcherWithUnit.matches());
+    assertEquals(doubleValue, matcherWithUnit.group(1).toString());
+    assertEquals("m^2", matcherWithUnit.group(2).toString());
+
+    Matcher matcherWithStrangeUnit = POV.NUMBER_PATTERN.matcher(doubleValue + " e");
+    assertTrue(matcherWithStrangeUnit.matches());
+    assertEquals(doubleValue, matcherWithStrangeUnit.group(1).toString());
+    assertEquals("e", matcherWithStrangeUnit.group(2).toString());
+  }
+}
diff --git a/src/test/java/org/caosdb/server/query/TestCQL.java b/src/test/java/org/caosdb/server/query/TestCQL.java
index 6d8f015d158aafe86baa087d6b56d38c0283ec62..8d7a7e8fb219f286d6cdaffc4b28240a7b2897d5 100644
--- a/src/test/java/org/caosdb/server/query/TestCQL.java
+++ b/src/test/java/org/caosdb/server/query/TestCQL.java
@@ -25,6 +25,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
@@ -46,6 +47,8 @@ import org.caosdb.server.query.Query.QueryException;
 import org.caosdb.server.utils.Initialization;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 
 public class TestCQL {
 
@@ -272,6 +275,7 @@ public class TestCQL {
   String issue131d = "FIND ename WITH (pname1.x) AND pname2";
   String issue131e = "FIND ename WITH (pname1.pname2 > 30) AND (pname1.pname2 < 40)";
   String issue131f = "FIND ename WITH (pname1.pname2 > 30) AND pname1.pname2 < 40";
+  String issue144 = "FIND ename WITH pname = ";
 
   // https://gitlab.com/caosdb/caosdb-server/-/issues/130
   String issue130a =
@@ -7016,6 +7020,57 @@ public class TestCQL {
     assertEquals("POV(null,LIKE ,%\"'bla%)", conj.getFilters().get(5).toString());
   }
 
+  @ParameterizedTest
+  @ValueSource(
+      strings = {
+        "1e+23",
+        "1E+23",
+        "5e22",
+        "5E22",
+        "2e-323",
+        "2E-323",
+        "-123",
+        "-1e23",
+        "3E15m^2",
+        "-3e15m",
+        "-3e15 1/s",
+        "3e15 m^2",
+        "+1",
+        "+2.234",
+        "+2.234e+23",
+        "+3.324E-23"
+      })
+  public void testIssue144(String scientific_notation) {
+    CQLLexer lexer;
+    lexer = new CQLLexer(CharStreams.fromString(this.issue144 + scientific_notation));
+    final CommonTokenStream tokens = new CommonTokenStream(lexer);
+
+    final CQLParser parser = new CQLParser(tokens);
+    final CqContext sfq = parser.cq();
+
+    for (final Token t : tokens.getTokens()) {
+      System.out.println(t.toString());
+    }
+
+    System.out.println(sfq.toStringTree(parser));
+
+    assertTrue(sfq.filter instanceof POV);
+    POV pov = (POV) sfq.filter;
+    assertEquals("POV(pname,=," + scientific_notation + ")", pov.toString());
+    assertTrue(pov.getVDouble() != null || pov.getVInt() != null);
+  }
+
+  @ParameterizedTest
+  @ValueSource(strings = {"- 123", "- 1e23", "2 e -23", "2E- 323", "+ 1"})
+  public void testIssue144WhiteSpaceInNumber(String number) {
+    CQLLexer lexer;
+    lexer = new CQLLexer(CharStreams.fromString(this.issue144 + number));
+    final CommonTokenStream tokens = new CommonTokenStream(lexer);
+
+    final CQLParser parser = new CQLParser(tokens);
+    assertThrowsExactly(Query.ParsingException.class, () -> parser.cq());
+  }
+
   /**
    * Test that brackets around 'has pname' do not cause filter to become subproperty filter.
    *