diff --git a/CHANGELOG b/CHANGELOG
index bc763f02f6f248c2ac299aabd0f29361a47ae8c1..bc33dd952e88e509592c8af8ec8a9ec48ae0a19c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -6,6 +6,7 @@ minerva (14.0.0~beta.2) unstable; urgency=low
   * Bug fix: removing overlays as curator in admin panel fixed (#944)
   * Bug fix: information about deprecated column is more clear about column 
     names (#838)
+  * Bug fix: version of the project is limited to 20 characters (#951)
 
  -- Piotr Gawron <piotr.gawron@uni.lu>  Mon, 16 Sep 2019 21:00:00 +0200
 
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectRestImpl.java
index 509e0f6cbdeaebcd006aa6492281ecfb83ab791e..7bfcf86676e664f94188e7ddd4c9bedd536dbe86 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectRestImpl.java
@@ -261,14 +261,13 @@ public class ProjectRestImpl extends BaseRestImpl {
         stringValue = (String) value;
       }
       if (fieldName.equalsIgnoreCase("version")) {
+        if (value != null && ((String) value).length() > 20) {
+          throw new QueryException("version is too long (>20 characters)");
+        }
         project.setVersion((String) value);
       } else if (fieldName.equalsIgnoreCase("id")) {
-        try {
-          int id = Integer.parseInt(stringValue);
-          if (id != project.getId()) {
-            throw new QueryException("Invalid id: " + stringValue);
-          }
-        } catch (NumberFormatException e) {
+        int id = parseInteger(stringValue, "id");
+        if (id != project.getId()) {
           throw new QueryException("Invalid id: " + stringValue);
         }
       } else if (fieldName.equalsIgnoreCase("projectId")) {
@@ -277,7 +276,7 @@ public class ProjectRestImpl extends BaseRestImpl {
         }
       } else if (fieldName.equalsIgnoreCase("name")) {
         if (value != null && ((String) value).length() > 255) {
-          throw new QueryException("name is too long");
+          throw new QueryException("name is too long (>255 characters)");
         }
         project.setName((String) value);
       } else if (fieldName.equalsIgnoreCase("notifyEmail")) {
@@ -387,6 +386,9 @@ public class ProjectRestImpl extends BaseRestImpl {
     params.sbgnFormat(getFirstValue(data.get("sbgn")));
     params.semanticZoomContainsMultipleLayouts(getFirstValue(data.get("semantic-zoom-contains-multiple-layouts")));
     params.version(getFirstValue(data.get("version")));
+    if (params.getVersion() != null && params.getVersion().length() > 20) {
+      throw new QueryException("version is too long (>20 characters)");
+    }
     params.annotations(getFirstValue(data.get("annotate")));
     params.setUser(user);
     MapCanvasType mapCanvasType;
diff --git a/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTest.java
index fd7624c9dae83917b984832122b68c90b420bbba..704933c43fb6cef01aa0f056443956b96c49e61a 100644
--- a/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTest.java
+++ b/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTest.java
@@ -34,8 +34,6 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest
   private static final String TEST_PROJECT = "test_project";
   private static final String CURATOR_PASSWORD = "test_pass";
   private static final String CURATOR_LOGIN = "test_user";
-  private static final String ADMIN_PASSWORD = "admin_pass";
-  private static final String ADMIN_LOGIN = "admin_user";
   Logger logger = LogManager.getLogger();
   @Autowired
   private IUserService userService;
@@ -44,18 +42,15 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest
   private ProjectDao projectDao;
 
   private User curator;
-  private User admin;
 
   @Before
   public void setup() {
     curator = createCurator(CURATOR_LOGIN, CURATOR_PASSWORD);
-
-    admin = createAdmin(ADMIN_LOGIN, ADMIN_PASSWORD);
   }
 
   @Test
   public void testGetAllProjectsAsAdmin() throws Exception {
-    MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD);
+    MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
     createProject(TEST_PROJECT);
 
     RequestBuilder request = get("/projects/")
@@ -136,7 +131,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest
   public void testGrantPrivilege() throws Exception {
     createProject(TEST_PROJECT);
 
-    MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD);
+    MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
 
     String body = "[{"
         + "\"privilegeType\":\"" + PrivilegeType.READ_PROJECT + "\", "
@@ -158,7 +153,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest
     Project project = createProject(TEST_PROJECT);
     userService.grantUserPrivilege(curator, PrivilegeType.READ_PROJECT, project.getProjectId());
 
-    MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD);
+    MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
 
     String body = "[{"
         + "\"privilegeType\":\"" + PrivilegeType.READ_PROJECT + "\", "
@@ -177,7 +172,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest
 
   @Test
   public void testGetNonExistingProject() throws Exception {
-    MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD);
+    MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
 
     RequestBuilder request = get("/projects/*/")
         .contentType(MediaType.APPLICATION_FORM_URLENCODED)
@@ -189,7 +184,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest
 
   @Test
   public void testUpdateProject() throws Exception {
-    MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD);
+    MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
     Project project = createProject(TEST_PROJECT);
 
     String content = "{\"project\":{\"version\":\"xxx\"}}";
@@ -206,9 +201,25 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest
 
   }
 
+  @Test
+  public void testUpdateProjectWithTooLongVersion() throws Exception {
+    MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
+    createProject(TEST_PROJECT);
+
+    String content = "{\"project\":{\"version\":\"12345678901234567890123456\"}}";
+
+    RequestBuilder request = patch("/projects/" + TEST_PROJECT + "/")
+        .contentType(MediaType.APPLICATION_FORM_URLENCODED)
+        .content(content)
+        .session(session);
+
+    mockMvc.perform(request)
+        .andExpect(status().isBadRequest());
+  }
+
   @Test
   public void testUpdateProjectWithUndefinedProjectId() throws Exception {
-    MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD);
+    MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
 
     String content = "{\"project\":{\"version\":\"xxx\"}}";
 
@@ -223,7 +234,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest
 
   @Test
   public void testGrantPrivilegeForUndefinedProject() throws Exception {
-    MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD);
+    MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
 
     String body = "[{"
         + "\"privilegeType\":\"" + PrivilegeType.READ_PROJECT + "\", "
@@ -240,7 +251,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest
 
   @Test
   public void testRevokePrivilegeForUndefinedProject() throws Exception {
-    MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD);
+    MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
 
     String body = "[{"
         + "\"privilegeType\":\"" + PrivilegeType.READ_PROJECT + "\", "
@@ -257,7 +268,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest
 
   @Test
   public void testRemoveProjectForUndefinedProjectId() throws Exception {
-    MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD);
+    MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
 
     RequestBuilder request = delete("/projects/*/")
         .session(session);
@@ -268,7 +279,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest
 
   @Test
   public void testGetStatisticsForUndefinedProjectId() throws Exception {
-    MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD);
+    MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
 
     RequestBuilder request = get("/projects/*/statistics")
         .session(session);
@@ -279,7 +290,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest
 
   @Test
   public void testDownloadSourceForUndefinedProjectId() throws Exception {
-    MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD);
+    MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
 
     RequestBuilder request = get("/projects/*:downloadSource")
         .session(session);
@@ -290,7 +301,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest
 
   @Test
   public void testGetLogsForUndefinedProjectId() throws Exception {
-    MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD);
+    MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
 
     RequestBuilder request = get("/projects/*/logs/")
         .session(session);
@@ -301,7 +312,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest
 
   @Test
   public void testGetSubmapConnectionsForUndefinedProjectId() throws Exception {
-    MockHttpSession session = createSession(ADMIN_LOGIN, ADMIN_PASSWORD);
+    MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
 
     RequestBuilder request = get("/projects/*/submapConnections/")
         .session(session);
diff --git a/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTestWithoutTransaction.java b/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTestWithoutTransaction.java
index bfc812723f1e17b5de435eb185d918146139a4df..553c289fe1058188119a42c739b1c4e08a70f9bc 100644
--- a/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTestWithoutTransaction.java
+++ b/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTestWithoutTransaction.java
@@ -130,6 +130,35 @@ public class ProjectControllerIntegrationTestWithoutTransaction extends Controll
     }
   }
 
+  @Test
+  public void addProjectWithTooLongVersion() throws Exception {
+    User admin = userService.getUserByLogin(BUILT_IN_ADMIN_LOGIN);
+    UploadedFileEntry fileEntry = createFileInSeparateThread(
+        new String(Files.readAllBytes(Paths.get("./src/test/resources/generic.xml")), "UTF-8"),
+        admin);
+    try {
+      String invalidVersion = "12345678901234567890123456";
+
+      String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList(
+          new BasicNameValuePair("file-id", String.valueOf(fileEntry.getId())),
+          new BasicNameValuePair("mapCanvasType", "OPEN_LAYERS"),
+          new BasicNameValuePair("version", invalidVersion),
+          new BasicNameValuePair("parser",
+              "lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser"))));
+
+      RequestBuilder request = post("/projects/" + TEST_PROJECT)
+          .contentType(MediaType.APPLICATION_FORM_URLENCODED)
+          .content(body)
+          .session(createSession(BUILT_IN_ADMIN_LOGIN, BUILT_IN_ADMIN_PASSWORD));
+
+      mockMvc.perform(request).andExpect(status().isBadRequest());
+
+    } finally {
+      removeFileInSeparateThread(fileEntry);
+      removeProjectInSeparateThread(TEST_PROJECT);
+    }
+  }
+
   @Test
   public void modifyProjectWithTooLongName() throws Exception {
     createProjectInSeparateThread(TEST_PROJECT);